Java-Swing窗体实现模拟驾考小程序

一,需求分析

二,概要设计

三,详细代码

  • 用户数据及题库文件(在项目根目录下创建dbfile文件夹)

User.txt :按如下格式写入用于存储用户数据文件

	17364658558-12345615618564958-12321617364658559-12345615618561234-123216

Question.txt :按如下格式写入用作题库文件(下面为示例)(题库可自己去度娘搜索爬取)

驾驶机动车遇到这种桥时首先怎样办?<br>A、保持匀速通过<br>B、尽快加速通过<br>C、低速缓慢通过<br>D、停车察明水情#D#jd5YTBB98px.jpg
图中哪个报警灯亮,提示充电电路异常或故障?<br>A、图1<br>B、图2<br>C、图3<br>D、图4#D#od6a10f8ed5c1f2f6ed07fa13d034ee69.jpg
驾驶机动车在下列哪种情形下不能超越前车?<br>A、前车减速让行<br>B、前车正在左转弯<br>C、前车靠边停车<br>D、前车正在右转弯#B
机动车仪表板上(如图所示)亮表示什么?<br>A、没有系好安全带<br>B、安全带出现故障<br>C、已经系好安全带<br>D、安全带系得过松#A#jdi2SYYBpIA.jpg
这个标志是何含义?<br>A、Y型交叉路口预告<br>B、十字交叉路口预告<br>C、丁字交叉路口预告<br>D、道路分叉处预告#C#odN8VNtIgFf.jpg
红色圆圈内标线含义是什么?<br>A、临时停靠站<br>B、大客车停靠站<br>C、公交车停靠站<br>D、应急停车带#C#odNskVJRX1L.jpg
这个标志是何含义?<br>A、立体交叉直行和右转弯行驶<br>B、立体交叉直行和左转弯行驶<br>C、直行和左转弯行驶<br>D、直行和右转弯行驶#B#odN8X6Cb6Mx.jpg
这个标志是何含义?<br>A、靠道路右侧停车<br>B、只准向右转弯<br>C、右侧是下坡路段<br>D、靠右侧道路行驶#D#odN8XhkvOi1.jpg
这个标志是何含义?<br>A、旅游区类别<br>B、旅游区距离<br>C、旅游区方向<br>D、旅游区符号#C#odNsSnvu8ub.jpg
车辆因故障必须在高速公路停车时,应在车后方多少米以外设置故障警告标志?<br>A、25<br>B、150<br>C、100<br>D、50#B
这个标志是何含义?<br>A、Y型交叉口<br>B、主路让行<br>C、注意分流<br>D、注意合流#D#od5hu0iyjzd.jpg

注: 带有图片的题目将题目图片放入根目录下创建的img文件夹放入(具体路径可自己指定)

  • 工具类(放在项目路径下的utils文件夹中)

MySpring.java

public class MySpring {private static HashMap<String,Object> beanBox = new HashMap<>();public static <T>T getBean(String className){T obj = null;try {obj = (T)beanBox.get(className);if(obj == null){Class clazz = Class.forName(className);obj = (T)clazz.newInstance();beanBox.put(className,obj);}} catch (Exception e) {e.printStackTrace();}return obj;}
}

QuestionFileReader.java

public class QuestionFileReader {private static HashSet<Question> questionBox = new HashSet<>();static {FileReader fr= null;BufferedReader bf= null;try {fr = new FileReader("src//dbfile//Question.txt");bf = new BufferedReader(fr);String question = bf.readLine();while (question!=null){String[] values = question.split("#");if(values.length==2){questionBox.add(new Question(values[0], values[1]));}else if(values.length==3){questionBox.add(new Question(values[0],values[1],values[2]));}question = bf.readLine();}} catch (Exception e) {e.printStackTrace();}finally {if (fr!=null){try {fr.close();} catch (IOException e) {e.printStackTrace();}}if (bf!=null){try {bf.close();} catch (IOException e) {e.printStackTrace();}}}}public HashSet<Question> getQuestionBox() {return questionBox;}
}

UserFileReader.java

public class UserFileReader {private static HashMap<String, User> userBox = new HashMap<>();public  static HashMap<String, User> getUserBox() {return userBox;}static {FileReader fileReader = null;BufferedReader bufferedReader = null;try {fileReader = new FileReader("src//dbfile//User.txt");bufferedReader= new BufferedReader(fileReader);String user = bufferedReader.readLine();while (user!=null){String[] value= user.split("-");userBox.put(value[0],new User(value[0],value[1]));user = bufferedReader.readLine();}} catch (Exception e) {e.printStackTrace();}finally {if(fileReader!=null){try {fileReader.close();} catch (Exception e) {e.printStackTrace();}}if (bufferedReader!=null){try {bufferedReader.close();} catch (IOException e) {e.printStackTrace();}}}}}
  • Dao数据持久层(放在项目路径下的dao文件夹中)

QuestionDao.java

public class QuestionDao {private QuestionFileReader fileReader = MySpring.getBean("util.QuestionFileReader");//HashSet 无get方法所以不能根据随机索引号获取题目;所以先使用ArrayList存储全部题目private  ArrayList<Question> questionPaper = new ArrayList(fileReader.getQuestionBox());public   ArrayList<Question> getPaper(int size){//由随机数获取的题目可能有重复的,用HashSet 去重复HashSet<Question> paper = new HashSet<>();while (paper.size()!=size) {Random r = new Random();int index = r.nextInt(this.questionPaper.size());paper.add(questionPaper.get(index));}//为了最后方便遍历最后再转用Arraylist 存储return new ArrayList<Question>(paper);}
}

UserDao.java

public class UserDao {public User selectOne(String acount){return UserFileReader.getUserBox().get(acount);}
}
  • Service业务逻辑层(放在项目路径下的service文件夹中)

UserService.java

public class UserService {private UserDao dao = MySpring.getBean("dao.UserDao");//登陆方法public String login(String account,String password){User user = dao.selectOne(account);while (user!=null){if(account.equals(user.getAccount())&&password.equals(user.getPassword())){return "登陆成功";}}return "账号或密码错误";}
}

QuestionService.java

public class QuestionService {private QuestionDao dao = MySpring.getBean("dao.QuestionDao");public ArrayList<Question> select(){return dao.getPaper(20);}
}
  • 数据映射类(放在项目路径下的domain文件夹中)

Question.java

//映射每一个问题
public class Question {private String title;private String answer;private String picture;public Question(){}public  Question(String title,String answer){this.title = title;this.answer = answer;}public Question(String title,String answer,String picture){this.title=title;this.answer=answer;this.picture=picture;}public void setTitle(String title) {this.title = title;}public void setAnswer(String answer) {this.answer = answer;}public void setPicture(String picture) { this.picture = picture; }public String getTitle() {return title;}public String getAnswer() {return answer;}public String getPicture() { return picture; }public boolean equals(Object obj) {if (this == (Question) obj) {return true;}if (obj instanceof Question) {if (this.title.substring(0,this.title.indexOf("
"
)).equals(((Question) obj).title.substring(0,this.title.indexOf("
"
)))) {return true;}}return false;}public int hashCode() {return this.getTitle().hashCode();} }

User.java

//映射每一个用户
public class User {private String account;private String password;public User(){}public User(String account, String password){this.account = account;this.password = password;}public String getAccount() {return account;}public String getPassword() {return password;}public void setAccount(String account) {this.account = account;}public void setPassword(String password) {this.password = password;}
}
  • 视图类(放在项目路径下的view文件夹中)

    BaseFrame.java

//模板模式
//设计一个规则 任何窗口想要画出来 执行流程固定
public abstract class BaseFrame extends JFrame {public BaseFrame(){}public BaseFrame(String title){super(title);}protected void init(){this.setFontAndSoOn();this.addElement();this.setFrameSelf();this.addListener();}//1,设置 字体颜色 背景 布局等protected abstract void setFontAndSoOn();//2,将属性添加1到窗体里protected abstract void addElement();//3,添加事件监听器protected abstract void addListener();//4,设置窗体自身protected abstract void setFrameSelf();
}

ExamFrame.java

public class ExamFrame extends BaseFrame {public ExamFrame(){this.init();}public ExamFrame(String title){super(title);this.init();}private QuestionService service = MySpring.getBean("service.QuestionService");private ArrayList<Question> paper = service.select();private int nowNum = 0;private int totalCount = paper.size();private int answerCount = 0;private int unanswerCount = totalCount;String[] realAnswer = new String[paper.size()];//初始化数组方法public void setArray(){for (int i=0;i<paper.size();i++){realAnswer[i] = "0";}}//创建一个线程对象 控制时间变化private TimeControlThread timeControlThread = new TimeControlThread();//用来记录时间private int time = 10;private JPanel mainPanel = new JPanel();private JPanel messagePanel = new JPanel();private JPanel buttonPanel = new JPanel();private JTextArea examArea = new JTextArea();private  JScrollPane scrollPane = new JScrollPane(examArea);private  JLabel pictureLabel = new JLabel();private JLabel nowNumLabel = new JLabel("当前题号:");private JLabel totalCountLabel = new JLabel("题目总数:");private JLabel answerCountLabel = new JLabel("已答题数:");private  JLabel unanswerCountLabel = new JLabel("未答题数");private JTextField nowNumField = new JTextField("0");private JTextField totalCountField = new JTextField("0");private JTextField answerCountField = new JTextField("0");private JTextField unanswerCountField = new JTextField("0");private  JLabel timeLabel = new JLabel("剩余答题时间");private JLabel realTimeLabel = new JLabel("01:00:00");private JButton aButton = new JButton("A");private JButton bButton = new JButton("B");private JButton cButton = new JButton("C");private JButton dButton = new JButton("D");private JButton prevButton = new JButton("上一题");private JButton submitButton = new JButton("交 卷");private JButton nextButton = new JButton("下一题");@Overrideprotected void setFontAndSoOn() {mainPanel.setLayout(null);mainPanel.setBackground(Color.lightGray);messagePanel.setLayout(null);messagePanel.setBounds(680,10,300,550);messagePanel.setBorder(BorderFactory.createLineBorder(Color.gray));buttonPanel.setLayout(null);buttonPanel.setBounds(16,470,650,90);buttonPanel.setBorder(BorderFactory.createLineBorder(Color.gray));scrollPane.setBounds(16,10,650,450);examArea.setFont(new Font("楷体", Font.BOLD,30));examArea.setBackground(Color.GRAY);examArea.setLineWrap(true);//自动换行examArea.setEnabled(false);pictureLabel.setBounds(10,10,280,230);pictureLabel.setBorder(BorderFactory.createLineBorder(Color.gray));//pictureLabel.setIcon(null);设置图片信息nowNumLabel.setBounds(40,270,100,30);nowNumLabel.setFont(new Font("楷体",Font.PLAIN,20));nowNumField.setBounds(150,270,100,30);nowNumField.setFont(new Font("黑体",Font.BOLD,20));nowNumField.setBorder(BorderFactory.createLineBorder(Color.gray));nowNumField.setEnabled(false);nowNumField.setHorizontalAlignment(JTextField.CENTER);totalCountLabel.setBounds(40,310,100,30);totalCountLabel.setFont(new Font("楷体",Font.PLAIN,20));totalCountField.setBounds(150,310,100,30);totalCountField.setFont(new Font("黑体",Font.BOLD,20));totalCountField.setBorder(BorderFactory.createLineBorder(Color.gray));totalCountField.setEnabled(false);totalCountField.setHorizontalAlignment(JTextField.CENTER);answerCountLabel.setBounds(40,350,100,30);answerCountLabel.setFont(new Font("楷体",Font.PLAIN,20));answerCountField.setBounds(150,350,100,30);answerCountField.setFont(new Font("黑体",Font.BOLD,20));answerCountField.setBorder(BorderFactory.createLineBorder(Color.gray));answerCountField.setEnabled(false);answerCountField.setHorizontalAlignment(JTextField.CENTER);unanswerCountLabel.setBounds(40,390,100,30);unanswerCountLabel.setFont(new Font("楷体",Font.PLAIN,20));unanswerCountField.setBounds(150,390,100,30);unanswerCountField.setFont(new Font("黑体",Font.BOLD,20));unanswerCountField.setBorder(BorderFactory.createLineBorder(Color.gray));unanswerCountField.setEnabled(false);unanswerCountField.setHorizontalAlignment(JTextField.CENTER);timeLabel.setBounds(90,460,150,30);timeLabel.setFont(new Font("楷体",Font.PLAIN,20));timeLabel.setForeground(Color.blue);realTimeLabel.setBounds(70,500,180,30);realTimeLabel.setFont(new Font("行楷",Font.BOLD,40));realTimeLabel.setForeground(Color.blue);aButton.setBounds(40,10,120,30);aButton.setFont(new Font("楷体", Font.BOLD,22));aButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));bButton.setBounds(190,10,120,30);bButton.setFont(new Font("楷体", Font.BOLD,22));bButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));cButton.setBounds(340,10,120,30);cButton.setFont(new Font("楷体", Font.BOLD,22));cButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));dButton.setBounds(490,10,120,30);dButton.setFont(new Font("楷体", Font.BOLD,22));dButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));prevButton.setBounds(40,50,100,30);prevButton.setFont(new Font("楷体", Font.BOLD,18));prevButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));nextButton.setBounds(510,50,100,30);nextButton.setFont(new Font("楷体", Font.BOLD,18));nowNumField.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));submitButton.setBounds(276,50,100,30);submitButton.setFont(new Font("楷体", Font.BOLD,18));submitButton.setForeground(Color.red);submitButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));this.showQuestion();nowNumField.setText(nowNum+1+"");totalCountField.setText(totalCount+"");answerCountField.setText(answerCount+"");unanswerCountField.setText(unanswerCount+"");}protected void addElement() {messagePanel.add(pictureLabel);messagePanel.add(nowNumLabel);messagePanel.add(nowNumField);messagePanel.add(totalCountLabel);messagePanel.add(totalCountField);messagePanel.add(answerCountLabel);messagePanel.add(answerCountField);messagePanel.add(unanswerCountLabel);messagePanel.add(unanswerCountField);messagePanel.add(timeLabel);messagePanel.add(realTimeLabel);buttonPanel.add(aButton);buttonPanel.add(bButton);buttonPanel.add(cButton);buttonPanel.add(dButton);buttonPanel.add(prevButton);buttonPanel.add(submitButton);buttonPanel.add(nextButton);mainPanel.add(scrollPane);mainPanel.add(messagePanel);mainPanel.add(buttonPanel);this.add(mainPanel);}boolean tag = false;//换题标签@Overrideprotected void addListener() {//绑定选项按钮事件监听器ActionListener listener = new ActionListener() {public void actionPerformed(ActionEvent e) {if(tag){answerCount--;}tag = true;ExamFrame.this.clearOptionButtonColor();JButton button =(JButton)e.getSource();button.setBackground(Color.yellow);realAnswer[nowNum] = button.getText();answerCountField.setText((++answerCount)+"");
//                System.out.println(answerCount);unanswerCountField.setText((totalCount-answerCount)+"");}};aButton.addActionListener(listener);bButton.addActionListener(listener);cButton.addActionListener(listener);dButton.addActionListener(listener);//绑定下一题按钮的事件监听器nextButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {ExamFrame.this.clearOptionButtonColor();nowNum++;if (nowNum==totalCount){examArea.setText("全部题目已经回答完毕\n请点击下方红色提交按钮");nextButton.setEnabled(false);ExamFrame.this.setOptionButtonEnabled(false);}else{ExamFrame.this.restormButton();ExamFrame.this.showQuestion();nowNumField.setText(nowNum+1+"");}}});//绑定上一题按钮的事件监听器,还原已选答案。prevButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {ExamFrame.this.clearOptionButtonColor();nowNum--;if(nowNum==0){prevButton.setEnabled(false);}nextButton.setEnabled(true);ExamFrame.this.showQuestion();ExamFrame.this.setOptionButtonEnabled(true);ExamFrame.this.restormButton();nowNumField.setText(nowNum+1+"");ExamFrame.this.restormButton();}});//绑定提交事件监听器submitButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {int value = JOptionPane.showConfirmDialog(ExamFrame.this,"是否确认提交试卷?");if(value==0) {//1.倒计时时间停止---线程处理timeControlThread.stopThread();//切换了线程的状态//2.所有按钮失效ExamFrame.this.setOptionButtonEnabled(false);//所有选项按钮失效prevButton.setEnabled(false);nextButton.setEnabled(false);//3.让按钮颜色回归本色ExamFrame.this.clearOptionButtonColor();//4.最终成绩的计算 展示在中间的文本域中float score = ExamFrame.this.checkPaper();examArea.setText("考试已经结束\n您最终的成绩为:" + score);submitButton.setEnabled(false);}}});}@Overrideprotected void setFrameSelf() {this.setBounds(440, 230, 1000, 600);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);this.setResizable(false);this.showQuestion();timeControlThread.start();this.setArray();}//展示题目public void showQuestion(){tag = false;Question q = paper.get(nowNum);String picture = q.getPicture();if(picture!=null){pictureLabel.setIcon(setPictureLabel("Src//img//"+picture));}else{pictureLabel.setIcon(null);}examArea.setText((nowNum+1)+"."+q.getTitle().replace("
"
,"\n"));}//展示题目图片public ImageIcon setPictureLabel(String picPath){ImageIcon imageIcon = new ImageIcon(picPath);imageIcon.setImage(imageIcon.getImage().getScaledInstance(280,230,Image.SCALE_DEFAULT));return imageIcon;}//用来清空所有选项按钮的颜色public void clearOptionButtonColor(){aButton.setBackground(null);bButton.setBackground(null);cButton.setBackground(null);dButton.setBackground(null);}//用来使所有的选择按钮失效public void setOptionButtonEnabled(boolean key){aButton.setEnabled(key);bButton.setEnabled(key);cButton.setEnabled(key);dButton.setEnabled(key);}//实现还原上一题的答案选项public void restormButton(){String value = realAnswer[nowNum];if(value==null){return ;}switch(value){case "A":aButton.setBackground(Color.YELLOW);break;case "B":bButton.setBackground(Color.YELLOW);break;case "C":cButton.setBackground(Color.YELLOW);break;case "D":dButton.setBackground(Color.YELLOW);break;default:this.clearOptionButtonColor();break;}}//改卷public float checkPaper(){float score = 100;for (int i = 0; i < paper.size();i++){if (!realAnswer[i].equals(paper.get(i).getAnswer())){score-=(100/paper.size());}}return score;}//一个内部类子线程用来处理考试时间private class TimeControlThread extends Thread{private boolean flag = true;public void stopThread() {this.flag=false;}public void run(){int hour = time/60;int minute = time%60;int second = 0;while (flag){if(hour==0&&minute==0&&second<=59){realTimeLabel.setForeground(Color.red);}StringBuilder timeString = new StringBuilder();//处理时if(hour>=0 && hour<10){timeString.append("0");}timeString.append(hour);timeString.append(":");//处理分if(minute>=0 && minute<10){timeString.append("0");}timeString.append(minute);timeString.append(":");//处理秒if(second>=0 && second<10){timeString.append("0");}timeString.append(second);realTimeLabel.setText(timeString.toString());try{Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}if (second>0){second--;}else {if (minute>0){minute--;second=59;}else {if (hour>0){hour--;minute=59;}else {realTimeLabel.setForeground(Color.RED);ExamFrame.this.setOptionButtonEnabled(false);prevButton.setEnabled(false);nextButton.setEnabled(false);JOptionPane.showMessageDialog(ExamFrame.this,"考试结束,请提交试卷");break;}}}}}} }

LoginFrame.java

public class LoginFrame extends BaseFrame {//重写构造方法public LoginFrame(){this.init();}public LoginFrame(String title){super(title);this.init();}//创建一个面板private JPanel mainPanel = new JPanel();//新建标签private JLabel titleLable = new JLabel("在 线 考 试 系 统");private JLabel acountLable = new JLabel("账 号:");private JLabel passwordLable = new JLabel("密 码:");//创建一个文本框private JTextField accountField = new JTextField();//创建一个密码框private JPasswordField passwordField = new JPasswordField( );//创建一个按钮private JButton loginButton = new JButton("登 陆");private JButton exitButton = new JButton("退 出");protected void setFontAndSoOn(){//设置panel的布局管理为自定义方式mainPanel.setLayout(null);//mainPanel.setBackground(Color.white);//设置每一个组件的位置titleLable.setBounds(120,40,340,35);//设置字体大小titleLable.setFont(new Font("黑体",Font.BOLD,34));//设置用户名label位置和字体大小acountLable.setBounds(94,124,90,30);acountLable.setFont(new Font("黑体",Font.BOLD,24));//设置用户名field位置和字体大小accountField.setBounds(204,124,260,30);accountField.setFont(new Font("黑体",Font.BOLD,24));//设置密码label位置和字体大小passwordLable.setBounds(94,174,90,30);passwordLable.setFont(new Font("黑体",Font.BOLD,24));//设置密码field位置和字体大小passwordField.setBounds(204,174,260,30);passwordField.setFont(new Font("黑体",Font.BOLD,24));//设置登陆按钮的位置和文字大小loginButton.setBounds(154,232,100,30);loginButton.setFont(new Font("黑体",Font.BOLD,24));//设置退出按钮的位置和文字大小exitButton.setBounds(304,232,100,30);exitButton.setFont(new Font("黑体",Font.BOLD,24));}//将组件添加到窗体protected void addElement(){mainPanel.add(titleLable);mainPanel.add(acountLable);mainPanel.add(accountField);mainPanel.add(passwordLable);mainPanel.add(passwordField);mainPanel.add(loginButton);mainPanel.add(exitButton);this.add(mainPanel);}//绑定事件监听器protected void addListener(){ActionListener listener = new ActionListener(){public void actionPerformed(ActionEvent e) {//1,获取用户的账号和密码//从登陆窗口上的组件内获取 文本框 密码框String account = accountField.getText();String password = new String(passwordField.getPassword());//调用之前的Service层的登陆方法UserService service = MySpring.getBean("service.UserService");String result = service.login(account,password);if (result.equals("登陆成功")){LoginFrame.this.setVisible(false);new ExamFrame("科目一模拟");}else {JOptionPane.showMessageDialog(LoginFrame.this,result);accountField.setText("");passwordField.setText("");}}};loginButton.addActionListener(listener);}//设置窗体自身属性protected void  setFrameSelf(){//设置窗体不可变化this.setResizable(false);//设置窗体可见this.setVisible(true);//设置窗体出现的位置及自身的宽高this.setBounds(600,300,560,340);//设置点击关闭按钮 窗体执行完毕this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}
  • 程序入口(放在项目路径下的test文件夹中)

Main.java

public class Main {public static void main(String[] args){new LoginFrame("登陆窗口");}
}

四,测试程序

The end… 文章仅供学习


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部