计应193第一组小学生做题软件——谢永波

                关于家长的痛点

1.用户愿景:

    随着生活节奏加快,加班和异地工作的人数逐渐增加,导致了许多问题的发生,主要因素在于分身乏术,不论是地理位置上的不便,还是时间上的不足,或者其他等原因,都导致的是家长难以对孩子进行看管,尤其是很多家长担心家里老人是否能监督的了孩子的学习。另一个令家长为难的事情是自己想监督辅导孩子的学习,不知如何下手。从学生的角度来看有一个可以练习习题的地方并不是一件坏事,更重要的一点是适时的给予家里的反馈使父母更加放心,很多时候学生想要时间上的自由,最简单的方法就是先把事情做了,而且还要被父母所看到。

2.需求分析:

    家长的需求:查看孩子学习的进度

      学生的需求:做题,简约的界面

      用户场景:

        

        

        

        

        

         

     需求更新:

        界面要清新简约,功能操作简单

        内容要有难度,知识点要全面,且具有一定深度

        家长界面只显示成绩和记录即可

     用户故事:

          楚留香:成绩中上游,对于成绩的提升有着强烈的渴望,希望可以发现自己的短板继而弥补,家长对于他也基于厚望,期望成绩的提升。

         段誉:成绩不好,对于提升成绩有着思想上的积极,行动上的消极,对于成绩快速提升有着不切实际的幻想,家长内心十分焦虑,极端渴望看到效果。

         张无忌:成绩优秀,抱着以好奇,和扩充知识点的想法来使用,心态上更加平和,家长对于他的成绩比较放心。

         段誉:对于成绩的波动,有着很大的反应,对于学生的成绩十分关心,希望每一步自己都能得到及时的反馈

         杨过:关心孩子的学习,但也仅止于此,只关注成绩的结果,对于学习的过程缺乏有效地关心

         乔峰:关心班里学生的成绩,担心有学生跟不上教学进度,希望学生能在课外追赶落后的进度

3.PSP个人流程图:

        

4.UML图:

        

5.代码:

        

package Frame;

import java.awt.Color;
import java.awt.Container;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

//小学生一百以内加减法的演练窗体
public class MathEasyQuestion {
    private  JFrame questionFrame=new JFrame();//创建窗体对象
    private  Container con = questionFrame.getContentPane();//获取窗体容器
    private  String projectPath =System.getProperty("user.dir")+"\WebContent";//获取项目中图片所在路径
    
    private JPanel questionPanel=new JPanel();//口算练习
    
    private int questionSum;//题目的数量
    private int currentIndex=0;//当前题目所在数组的下标
    private int firstError=0;//找到第一个出错题目的下标,没有则返回到0所在的题目
    private int errorSum;//本次练习中错误的题目数量
    private int rightSum=0;//本次练习中正确的题目数量

    
    private String[] questions;//题目的内容
    private String[] results;//题目的结果
    private String[] resultUser;//用户输入的结果
    private int[] statusNarrate;//状态描述
    
    private JLabel questionNarrate=new JLabel();//题目描述
    private JLabel questionLabel=new JLabel();//题目标签
    private JTextField questionText=new JTextField();//输入结果文本框
    private JLabel answerLabel=new JLabel();//答案标签
    private JLabel resultLabel=new JLabel();//结果显示框
    private JLabel statusLabel=new JLabel();//状态显示框
    
    JLabel progressLabel=new JLabel();//进度条
    
    private JButton submitButton=new JButton();//提交按钮
    private JButton restartButton=new JButton();//重新测验按钮
    private JButton precedingButton=new JButton();//上一题
    private JButton nextButton=new JButton();//下一题
    private JButton precedingPage=new JButton();//返回主窗口
    
    private Timer timer=new Timer();//计时器
    private JLabel timerLabel=new JLabel();//计时器标签
    private int secondTime=0;//本次练习所花费的秒数
    private String overtime;//格式化后的时间
    
    private MainFrame mainFrame=new MainFrame();//主界面窗体
    
    private JLabel conclusion=new JLabel();//结论
    
    //练习题的标签
    
    JLabel label7=new JLabel();
    JLabel label8=new JLabel();
    JLabel label9=new JLabel();
    JLabel label10=new JLabel();
    
    JLabel label11=new JLabel();
    JLabel label12=new JLabel();
    JLabel label13=new JLabel();
    
    
    
    public MathEasyQuestion(int sum) {
        //定义数组和变量
        questionSum=sum;
        questions=new String[sum];
        results=new String[sum];
        resultUser=new String[sum];
        statusNarrate=new int[sum];
        errorSum=questionSum;
        
        generateQuestions(sum);//生成指定数量的题目
        
        questionFrame.setTitle("乐学");
        questionFrame.setVisible(true);
        int width = Toolkit.getDefaultToolkit().getScreenSize().width;
        int height = Toolkit.getDefaultToolkit().getScreenSize().height;
        // 定义窗体的宽高
        int windowsWedth = 500;
        int windowsHeight = 500;
        Image m = null;
        try {
            m = ImageIO.read(new FileInputStream(projectPath+"\head\astronaut.jpg"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        questionFrame.setIconImage(m);
        questionFrame.setBounds((width - windowsWedth) / 2,
                (height - windowsHeight) / 2, windowsWedth, windowsHeight);
        
        questionFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        questionFrame.setVisible(true);
        questionFrame.setLayout(null);
        questionFrame.setResizable(false);
        
        questionsPanel();
        setTimer();
    }
    
    //创建包含控件的Panel对象
    private void questionsPanel() {
        questionPanel.setBounds(50,60,390,330);
        questionPanel.setBackground(Color.white);
        questionPanel.setVisible(true);
        questionPanel.setLayout(null);
        //Border mathBorder=new Border();
        questionPanel.setBorder(BorderFactory.createTitledBorder("口算练习"));
        
        setStatusLabel();
        setQuestionScale();
        setSubmitButton();
        setPrecedingButton();
        setNextButton();
        setProgress();
        setPrecedingPage();
        setRestartButton();
        setTimerLabel();
        
        con.add(questionPanel);
    }
    
    //练习的原始状态设置 并为用户输入框添加事件获取值
    private void setQuestionScale() {
        questionLabel.setBounds(50,70,70,30);
        questionLabel.setText("<html><body><p style='font-size:14px;'>"+"题目:"+"</p></body></html>");
        answerLabel.setBounds(50,120,70,30);
        answerLabel.setVisible(false);
        answerLabel.setText("<html><body><p style='font-size:14px;'>"+"答案:"+"</p></body></html>");
        questionNarrate.setBounds(120,70,100,30);
        questionNarrate.setText("<html><body><p style='font-size:14px;'>"+questions[currentIndex]+"</p></body></html>");
        
        questionText.setBounds(200,75,80,30);
        questionText.addFocusListener(new FocusListener() {

            @Override
            public void focusGained(FocusEvent arg0) {
                // TODO Auto-generated method stub
                
            }
            //一旦文本框失去焦点则将文本框内的内容写进数组
            @Override
            public void focusLost(FocusEvent arg0) {
                // TODO Auto-generated method stub
                        resultUser[currentIndex]=questionText.getText();
            }});
        
        resultLabel.setBounds(120,120,80,30);
        resultLabel.setVisible(false);
        resultLabel.setText("<html><body><p style='font-size:14px;'>"+String.valueOf(results[currentIndex])+"</p></body></html>");
        questionPanel.add(questionNarrate);
        questionPanel.add(questionText);
        questionPanel.add(resultLabel);
        questionPanel.add(questionLabel);
        questionPanel.add(answerLabel);
    }
    
    //设置重新开始按钮
    private void setRestartButton() {
        restartButton.setBounds(160,260,80,30);
        restartButton.setVisible(false);
        restartButton.setText("继续");
        restartButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                // TODO Auto-generated method stub
                questionFrame.dispose();
                new MathEasyQuestion(questionSum);
            }
            
        });
        questionPanel.add(restartButton);
    }
    
    //设置计时器
    private void setTimer() {
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                secondTime+=1;//计时器自动叠加秒数
                long millisecond=secondTime*1000;//将秒数转为毫秒数
                SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");//设置时间格式
                overtime=formatter.format(millisecond);
                timerLabel.setText("<html><body><p style='font-size:14px;'>时间:"+overtime+"</p></body></html>");
            }}, 1000, 1000);//延迟一秒 间隔一秒
    }
    
    //设置计时器标签
    private void setTimerLabel() {
        timerLabel.setBounds(240,20,210,30);
        timerLabel.setText("<html><body><p style='font-size:14px;'>时间:"+String.valueOf(secondTime)+"</p></body></html>");
        questionPanel.add(timerLabel);
    }
    
    //设置包含对错图形的标签,并设置为不可见
    private void setStatusLabel() {
        statusLabel.setBounds(320,70,30,30);
        statusLabel.setVisible(false);
        questionPanel.add(statusLabel);
    }

    //为对错标签添加图片
    private void setStatusPicture(String picture) {
        Image image = Toolkit.getDefaultToolkit().getImage(projectPath+picture);
        ImageIcon icon=new  ImageIcon(image);
        icon.setImage(icon.getImage().getScaledInstance(statusLabel.getWidth(),statusLabel.getHeight(),Image.SCALE_DEFAULT ));
        statusLabel.setIcon(icon);
    }
    
    //设置交卷后的综合评价标签
    private void setConclusion(String words) {
        conclusion.setBounds(100,160,300,70);
        conclusion.setVisible(true);
        conclusion.setText(words);
        questionPanel.add(conclusion);
    }
    
    //设置当前题目页数与总的题目页数
    private void setProgress() {
        progressLabel.setBounds(180,20,50,30);
        progressLabel.setText("<html><body><p style='font-size:14px;'>"+(currentIndex+1)+"/"+questionSum+"</p></body></html>");
        questionPanel.add(progressLabel);
    }
    //设置提交按钮,计算用户输入的值是否正确,将一些标签设置为可见,显示结果
    private void setSubmitButton() {
        submitButton.setBounds(160,260,80,30);
        submitButton.setText("交卷");
        submitButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                // TODO Auto-generated method stub
                timer.cancel();
                comparison();
                statusLabel.setVisible(true);
                answerLabel.setVisible(true);
                resultLabel.setVisible(true);
                conclusion.setVisible(true);
                //交卷后下标将回到第一个出错的页面,全对则到第一道题所在的页面
                for(int z=0;z<questionSum;z++) {
                    if(statusNarrate[z]==1) {
                        firstError=z;
                        break;
                    }    
                }
                currentIndex=firstError;
                changeQuestion();
                
                //设置用户输入框为不可修改
                questionText.setEditable(false);
                
                //显示测试结果以及评价
                double rightRate;
                if(errorSum==0) {
                    rightRate=1;
                }else if(rightSum==0) {
                    rightRate=0;
                }else {
                    rightRate=(double)(Math.round((rightSum/questionSum)*100))/100;
                }
                setConclusion("<html><body><p style='font-size:11px;'>正确的数量:"+rightSum+"&nbsp&nbsp&nbsp&nbsp"
                        + "错误的数量:"+errorSum+"<br>"
                        + "准确率:"+rightRate+"&nbsp&nbsp&nbsp&nbsp"
                        + "耗费时长:" +overtime
                        + "<br>评语:" +evaluate(rightRate)+"</p></body></html>");
                
                //设置交卷按钮为不可见,并设置开始按钮为可见
                submitButton.setVisible(false);
                restartButton.setVisible(true);
                
            }});
        questionPanel.add(submitButton);
    }
    
    //根据正确率来进行评价
    private String evaluate(double rightRate) {
        if(rightRate==1) {
            return "太棒了!全对了";
        }else if(rightRate>0.9) {
            return "距离完美只差一点点了";
        }else if(rightRate>0.8) {
            return "看来我们需要更多的练习了";
        }else if(rightRate>0.6) {
            return "看来我们并不是只有表面的差距";
        }else if(rightRate>0.3) {
            return "不放弃,每一步,都是胜利";
        }else {
            return "不要气馁!还有希望";
        }
    }
    
    //比较用户输入的值和题目的答案
    private void comparison() {
        for(int i=0;i<questionSum;i++) {
            if(results[i].equals(resultUser[i])) {
                statusNarrate[i]=0;//0表示正确
                errorSum-=1;
                rightSum+=1;
            }else {
                statusNarrate[i]=1;//1表示错误
            }
        }
    }
    
    //创建上一题按钮,并添加事件,改变标签的内容和图片
    private void setPrecedingButton() {
        precedingButton.setBounds(50,260,80,30);
        precedingButton.setText("上一题");
        questionPanel.add(precedingButton);
        precedingButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                // TODO Auto-generated method stub
                if(currentIndex!=0) {
                    currentIndex-=1;//改变题目的下标
                    changeQuestion();
                }
            }
            
        });
    }
    
    //创建上一题按钮,并添加事件,改变标签的内容和图片
    private void setNextButton() {
        nextButton.setBounds(260,260,80,30);
        nextButton.setText("下一题");
        nextButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                // TODO Auto-generated method stub
                if(currentIndex!=(questionSum-1)) {
                    currentIndex+=1;//改变题目的下标
                    changeQuestion();
                }
            }
            
        });
        
        questionPanel.add(nextButton);
    }
    
    //跳转到currentIndex值指定的界面
    private void changeQuestion() {
        questionNarrate.setText("<html><body><p style='font-size:14px;'>"+questions[currentIndex]+"</p></body></html>");
        resultLabel.setText(String.valueOf("<html><body><p style='font-size:14px;'>"+results[currentIndex])+"</p></body></html>");
        progressLabel.setText("<html><body><p style='font-size:14px;'>"+(currentIndex+1)+"/"+questionSum+"</p></body></html>");
        
        //在切换题目的时候,如果是之前写过的内容则显示在文本框
        if(resultUser[currentIndex]!=null) {
            questionText.setText(String.valueOf(resultUser[currentIndex]));
        }else {
            questionText.setText("");
        }
        
        //questionText.setText("");//更换题目之后将文本框清空
        if(statusNarrate[currentIndex]==0) {
            setStatusPicture("\head\right.jpg");//0表示正确
        }else if(statusNarrate[currentIndex]==1){
            setStatusPicture("\head\fail.jpg");//1表示正确
        }
    }
    
    //生成一百以内加减法的题目
    public void generateQuestions(int index) {
        for(int i=0;i<index;i++) {
            int j=(int)(1+Math.random()*(100-1+1));
            int z=(int)(1+Math.random()*(100-1+1));
            if(j-z<100&&j-z>0) {
                questions[i]=String.valueOf(j)+"-"+String.valueOf(z);
                results[i]=String.valueOf(j-z);
            }else if(j+z<100&&j+z>0) {
                questions[i]=String.valueOf(j)+"+"+String.valueOf(z);
                results[i]=String.valueOf(j+z);
            }else if(z-j<100&&z-j>0) {
                questions[i]=String.valueOf(z)+"-"+String.valueOf(j);
                results[i]=String.valueOf(z-j);
            }
        }
    }
    
    //设置返回主界面按钮
    private void setPrecedingPage() {
        precedingPage.setBounds(50,25,100,30);
        precedingPage.setText("《=主界面");
        precedingPage.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                // TODO Auto-generated method stub
                questionFrame.dispose();
                mainFrame.loadmain();
            }});
        questionPanel.add(precedingPage);
    }
    
    
    
    public static void main(String[] args) {
        MathEasyQuestion meq=new MathEasyQuestion(5);
    }
    
}

 6:示例图

      

原文地址:https://www.cnblogs.com/bladepoint/p/14756713.html