1 实训基本信息
1.1 实训项目名称
(1)考试系统
1.2 实训环境
本次实训内容主要针对专业学生,实训形式以实战讲解为主导。实训课程由实训老师主讲,实训老师教学严谨又平易近人,讲解的内容非常细致和认真,对于重要的知识点内容老师还特意的标注下来,方便同学们回顾学习。
2 实训内容简介
2.1 考试系统
考试系统是一种可以从题库中随机抽取指定题目数量的系统,主要由Java开发环境JDK、集成开发环境Eclipse、数据库管理系统软件MySQL和数据库图形化管理工具Navicat 相结合而构成。
通过在数据库中创建Test表和Recoed表,建立与数据库的连接,即程序与数据库之间的桥梁,并向数据库发送SQL语句,利用程序把具体的数据库操作发送出去,实现程序对数据库进行增加、删除、更改、查找以及从数据库中随机抽题的操作,最后处理从数据库返回的操作结果。
考试界面由窗体类、菜单和事件代码组成,通过单击开始考试,系统从数据库中随机抽题,并将抽取题目显示在文本区中,用户可以点击下一题继续答题,也可以选择上一题更改之前的选项,最后点击提交完成考试,系统通过游戏记录来记录本次考试,用户可以通过记录查看本次考试。
3 项目开发过程
3.1 考试系统
数据库管理系统软件MySQL和数据库图形化管理工具Navicat,使用JDBC完成数据库与Java建立连接,向数据库发送SQL语句,处理从数据库返回的操作结果;
3.2 开发步骤
1、数据库的连接和使用:
通过在数据库中创建Test表和Recoed表,使用JDBC完成数据库与Java建立连接建立与数据库的连接,即程序与数据库之间的桥梁,并向数据库发送SQL语句,利用程序把具体的数据库操作发送出去,实现程序对数据库进行增加、删除、更改、查找以及从数据库中随机抽题的操作,最后处理从数据库返回的操作结果。
2、考试界面设计:
考试界面由窗体类、菜单和事件代码组成,通过单击开始考试,系统从数据库中随机抽题,并将抽取题目显示在文本区中,用户可以点击下一题继续答题,也可以选择上一题更改之前的选项,最后点击提交完成考试,系统通过游戏记录来记录本次考试,用户可以通过记录查看本次考试。
3、开始考试功能:
单击开始考试,抽取10道题放到一个集合中,并定义一个集合list存储抽到的题,将用户选择的答案保存在test对象中,增加一个成员变量,保存用户的答案,修改Test类,成员变量userda,写答案到test中,用一个方法实现,把修改后的test替换集合中的相应元素,按钮组的所有选项清空;
4、上一题下一题显示功能:
Index实现加1,显示下一道题,上一题按钮可用,下一题按钮在index=9按钮不可用,单击上一题按钮,将当前选项答案存入集合,显示下一道题,index=0按钮不可用,当用户回看做过的题时,保留之前的选择,代码写在printjm中。
5、提交并记录成绩功能:
点击提交按钮,比对用户答案和正确答案之间是否相等,给出成绩,并将用户名称和成绩存入record表。
6、查看成绩记录功能:
查询record表中的所有记录,显示在jta的文本区中,结果存在一个集合里,集合中的每一个元素就是一条记录,用Record类的对象表示,RecordDao类中的方法public static ArrayList<Record> findAll(){…},调用方法findAll获取集合数据,遍历集合获取每一个元素的值,将元素值显示在文本区中。
4 系统截图
5 程序源代码
登录界面部分(用户名:root 密码:123)
1. import javax.swing.*; 2. import javax.swing.plaf.FontUIResource; 3. 4. import java.awt.*; 5. import java.awt.event.ActionEvent; 6. import java.awt.event.ActionListener; 7. import java.util.Enumeration; 8. 9. public class Login extends JFrame implements ActionListener { 10. // 定义主窗口 11. private JFrame jf; 12. // 定义输入用户名和密码的标签提示 13. private JLabel InputUserName; 14. private JLabel InputPassWord; 15. // 定义输入用户名文本框 16. private JTextField UserName; 17. // 定义输入密码框 18. private JPasswordField PassWord; 19. // 定义登录和取消按钮 20. private JButton Login; 21. private JButton Cancel; 22. JRadioButton stu,tea; 23. Login() { 24. // 各组件实例化过程 25. setTitle("登录"); 26. InitGlobalFont(new Font("黑体", Font.PLAIN, 20)); 27. InputUserName = new JLabel(" 用户名: "); 28. InputPassWord = new JLabel(" 密 码: "); 29. UserName = new JTextField(); 30. PassWord = new JPasswordField(); 31. ButtonGroup bg=new ButtonGroup(); 32. bg.add(stu); 33. bg.add(tea); 34. Login = new JButton("登录"); 35. Cancel = new JButton("取消"); 36. // 设置主窗口大小、位置和布局 37. setSize(500, 200); 38. setLocation(600, 400); 39. // 设置窗口流式布局 40. setLayout(new FlowLayout()); 41. // 设置用户名和密码框大小 42. UserName.setPreferredSize(new Dimension(300, 30)); 43. PassWord.setPreferredSize(new Dimension(300, 30)); 44. 45. // 依次向主窗口添加各组件 46. add(InputUserName); 47. add(UserName); 48. add(InputPassWord); 49. add(PassWord); 50. add(Login); 51. add(Cancel); 52. // 设置主窗口不可调节大小 53. setResizable(false); 54. // 设置主窗口默认关闭操作 55. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 56. // 给登录和取消按钮添加 Action 监听器 57. Login.addActionListener(this); 58. Cancel.addActionListener(this); 59. // 设置主窗口可见 60. setVisible(true); 61. } 62. 63. @Override 64. public void actionPerformed(ActionEvent e) { 65. // 如果单击【退出】按钮则程序退出 66. if (e.getSource().equals(Cancel)) { 67. System.exit(0); 68. } 69. // 如果单击【登录】按钮则检查用户名和密码是否匹配 70. else if (e.getSource().equals(Login)) { 71. // 如果用户名和密码匹配,则打开具体操作面板 72. if (UserName.getText().equals("root") && String.valueOf(PassWord.getPassword()).equals("123")) { 73. 74. new ExamJFrame(); 75. setVisible(false); 76. dispose(); 77. 78. } 79. // 如果用户名和密码不匹配,则给出提示对话框 80. else { 81. JOptionPane.showOptionDialog(jf, "输入有误", "登陆失败", 82. JOptionPane.CLOSED_OPTION, 83. JOptionPane.ERROR_MESSAGE, null, null, null); 84. } 85. 86. } 87. } 88. 89. /** 90. * 统一设置字体,父界面设置之后,所有由父界面进入的子界面都不需要再次设置字体 91. */ 92. private static void InitGlobalFont(Font font) { 93. FontUIResource fontRes = new FontUIResource(font); 94. for (Enumeration<Object> keys = UIManager.getDefaults().keys(); keys.hasMoreElements();) { 95. Object key = keys.nextElement(); 96. Object value = UIManager.get(key); 97. if (value instanceof FontUIResource) { 98. UIManager.put(key, fontRes); 99. } 100. } 101. } 102. public static void main(String[] args) { 103. new Login(); 104. } 105. }
数据库连接与记录
1. import java.io.IOException; 2. import java.sql.Connection; 3. import java.sql.DriverManager; 4. import java.sql.ResultSet; 5. import java.sql.SQLException; 6. import java.sql.Statement; 7. import java.util.ArrayList; 8. 9. import com.sun.prism.impl.Disposer.Record; 10. 11. /* 12. * 用户记录表的数据库访问 13. */ 14. public class RecordDao { 15. public static Connection conn = null; 16. //获取访问mytest的连接对象 17. public static Connection getConnection(){ 18. // 1、加载驱动 19. try { 20. Class.forName("com.mysql.jdbc.Driver"); 21. } catch (ClassNotFoundException e) { 22. // TODO Auto-generated catch block 23. e.printStackTrace(); 24. } 25. // 2、通过驱动管理器调用方法创建连接对象 26. String url = "jdbc:mysql://localhost:3306/test01?useUnicode=true&characterEncoding=utf8"; 27. String user = "root";// MySQL中默认访问的用户名 28. String password = "123"; 29. 30. try { 31. conn = DriverManager.getConnection(url, user, password); 32. } catch (SQLException e) { 33. // TODO Auto-generated catch block 34. e.printStackTrace(); 35. } 36. return conn; 37. } 38. //record表添加记录 39. //Record re 参数 40. public static int addrecord(管理系统02.Record re){ 41. int flag=0; 42. String sql="insert into record (name,score) values('"+re.getName() 43. +"',"+re.getScore()+")"; 44. System.out.println(sql); 45. //创建连接对象 46. conn=getConnection(); 47. //创建命令对象 48. Statement stmt=null; 49. try{ 50. stmt=conn.createStatement(); 51. //执行添加记录操作 52. flag=stmt.executeUpdate(sql); 53. }catch(SQLException e){ 54. e.printStackTrace(); 55. } 56. return flag; 57. } 58. //查询用户分数表中所有记录 59. public static ArrayList<Record> findAll(){ 60. conn=getConnection(); 61. Statement stmt=null; 62. //创建一个集合对象 63. ArrayList<Record> list=new ArrayList<Record>(); 64. //创建集合中的元素 65. Record re; 66. //创建命令对象 67. try { 68. stmt=conn.createStatement(); 69. String sql="select * from record "; 70. ResultSet rs = stmt.executeQuery(sql); 71. // while(rs.next()){ 72. // //对元素对象初始化 73. // re=new Record(); 74. // //对元素的成员进行赋值 75. // re.setId(rs.getInt(1)); 76. // re.setName(rs.getString(2)); 77. // re.setScore(rs.getInt(3)); 78. // // System.out.println(re); 79. // //添加元素到集合 80. // list.add(re); 81. // } 82. } catch (SQLException e) { 83. // TODO Auto-generated catch block 84. e.printStackTrace(); 85. } 86. try { 87. stmt.close(); 88. conn.close(); 89. } catch (SQLException e) { 90. // TODO Auto-generated catch block 91. e.printStackTrace(); 92. } 93. 94. return list; 95. } 96. public static void main(String[] args) { 97. } 98. }
存储随机抽取的题目
1. //试题类,存储每一道题的类 2. public class Test { 3. private int id; 4. private String content; 5. private String sa; 6. private String sb; 7. private String sc; 8. private String sd; 9. private String answer; 10. private String userda="E"; 11. 12. public Test() { 13. super(); 14. // TODO 自动生成的构造函数存根 15. } 16. public String getUserda() { 17. return userda; 18. } 19. public int getId() { 20. return id; 21. } 22. public void setId(int id) { 23. this.id = id; 24. } 25. public String getContent() { 26. return content; 27. } 28. public void setContent(String content) { 29. this.content = content; 30. } 31. public String getSa() { 32. return sa; 33. } 34. public void setSa(String sa) { 35. this.sa = sa; 36. } 37. public String getSb() { 38. return sb; 39. } 40. public void setSb(String sb) { 41. this.sb = sb; 42. } 43. public String getSc() { 44. return sc; 45. } 46. public void setSc(String sc) { 47. this.sc = sc; 48. } 49. public String getSd() { 50. return sd; 51. } 52. public void setSd(String sd) { 53. this.sd = sd; 54. } 55. public String getAnswer() { 56. return answer; 57. } 58. public void setAnswer(String answer) { 59. this.answer = answer; 60. } 61. public void setUserda(String userda) { 62. this.userda = userda; 63. } 64. }
随机抽取10道题并核对答案
1. import java.sql.Connection; 2. import java.sql.DriverManager; 3. import java.sql.ResultSet; 4. import java.sql.SQLException; 5. import java.util.ArrayList; 6. 7. import com.mysql.jdbc.Statement; 8. 9. public class TestD { 10. public static Connection conn = null; 11. //获取访问mytest的连接对象 12. public static Connection getConnection() { 13. try { 14. Class.forName("com.mysql.jdbc.Driver"); 15. System.out.println("驱动加载成功"); 16. }catch (ClassNotFoundException e) { 17. e.printStackTrace(); 18. System.out.println("驱动加载失败"); 19. } 20. String url="jdbc:mysql://localhost:3306/test01"; 21. String user="root"; 22. String password="123"; 23. try { 24. conn = DriverManager.getConnection(url,user,password); 25. }catch (SQLException e) { 26. e.printStackTrace(); 27. } 28. return conn; 29. } 30. public static ArrayList<Test> find10(){ 31. conn=getConnection(); 32. Statement stmt=null; 33. //创建一个集合对象 34. ArrayList<Test> list = new ArrayList<Test>(); 35. //创建集合中的元素 36. Test test; 37. //创建命令对象 38. try { 39. stmt=(Statement) conn.createStatement(); 40. String sql = "select * from test order by rand() limit 10"; 41. ResultSet rs = stmt.executeQuery(sql); 42. while(rs.next()) { 43. //元素对象初始化 44. test=new Test(); 45. //进行赋值 46. test.setId(rs.getInt(1)); 47. test.setContent(rs.getString(2)); 48. test.setSa(rs.getString(3)); 49. test.setSb(rs.getString(4)); 50. test.setSc(rs.getString(5)); 51. test.setSd(rs.getString(6)); 52. test.setAnswer(rs.getString(7)); 53. //添加元素到集合 54. list.add(test); 55. } 56. } catch (SQLException e) { 57. // TODO Auto-generated catch block 58. e.printStackTrace(); 59. } 60. try { 61. stmt.close(); 62. conn.close(); 63. } catch (SQLException e) { 64. // TODO Auto-generated catch block 65. e.printStackTrace(); 66. } 67. 68. return list; 69. } 70. public static void main(String[] args) { 71. } 72. }
系统主界面部分
1. import java.awt.BorderLayout; 2. import java.awt.Font; 3. import java.awt.GridLayout; 4. import java.awt.event.ActionEvent; 5. import java.awt.event.ActionListener; 6. import java.util.ArrayList; 7. import java.util.Enumeration; 8. import java.util.List; 9. 10. import javax.swing.ButtonGroup; 11. import javax.swing.JButton; 12. import javax.swing.JFrame; 13. import javax.swing.JLabel; 14. import javax.swing.JMenu; 15. import javax.swing.JMenuBar; 16. import javax.swing.JMenuItem; 17. import javax.swing.JOptionPane; 18. import javax.swing.JPanel; 19. import javax.swing.JRadioButton; 20. import javax.swing.JScrollPane; 21. import javax.swing.JTextArea; 22. import javax.swing.UIManager; 23. import javax.swing.plaf.FontUIResource; 24. 25. import 管理系统02.Record; 26. 27. /* 28. * 主窗体 29. */ 30. public class ExamJFrame extends JFrame{ 31. JMenuBar jmb; 32. JMenu jm,jm2; 33. JMenuItem jmi1,jmi2; 34. JPanel jp1; 35. JLabel jlb;//题目 36. JRadioButton jr1,jr2,jr3,jr4;//四个选项的单选按钮 37. JButton jb1,jb2,jb3;//三个按钮,上一题、下一题、提交 38. JPanel jp2;//用来放三个按钮 39. ButtonGroup bg;//按钮组,实现单选按钮的排斥 40. JTextArea jta; 41. Test test; 42. ArrayList<Test> list; 43. int index; 44. 45. ExamJFrame(){ 46. setTitle("考试系统"); 47. setSize(700, 500); 48. setLocationRelativeTo(null); 49. InitGlobalFont(new Font("黑体", Font.PLAIN, 20)); 50. init(); 51. setDefaultCloseOperation(EXIT_ON_CLOSE); 52. setVisible(true); 53. jmi1.addActionListener(new ActionListener() { 54. 55. @Override 56. public void actionPerformed(ActionEvent e) { 57. init2(); 58. //抽取10道题到集合 59. list=TestD.find10(); 60. //显示第一题到页面中 61. index=0; 62. //把index索引的值显示在界面中 63. printjm(index); 64. //上一题按钮不可用 65. jb1.setEnabled(false); 66. } 67. }); 68. jmi2.addActionListener(new ActionListener() { 69. 70. @Override 71. public void actionPerformed(ActionEvent e) { 72. init3(); 73. } 74. }); 75. } 76. //定义查询记录的界面 77. public void init3() { 78. jp1.removeAll(); 79. jp1.setLayout(new BorderLayout()); 80. jta=new JTextArea(); 81. 82. JScrollPane jsp=new JScrollPane(jta); 83. jp1.add(jta); 84. //调用方法findAll获取集合数据 85. ArrayList<Record> relist=Record.findAll(); 86. //遍历集合获取每一个元素的值 87. for(int i=0;i<relist.size();i++) { 88. //获取每一个元素 89. Record re=relist.get(i); 90. //元素表示每个用户的分数放在字符串中 91. String str="序号:"+re.getId()+" \t姓名:"+re.getName()+"\t成绩:"+re.getScore()+"\r\n"; 92. //将元素值显示在文本区中,不能用setTest方法 93. jta.append(str); 94. } 95. 96. this.validate(); 97. } 98. //设置初始界面 99. public void init() { 100. jmb=new JMenuBar(); 101. jm=new JMenu("考试"); 102. jm2=new JMenu("考试记录"); 103. jmi1=new JMenuItem("开始考试"); 104. jmi2=new JMenuItem("查询所有考试记录"); 105. jm.add(jmi1); 106. jm2.add(jmi2); 107. jmb.add(jm); 108. jmb.add(jm2); 109. setJMenuBar(jmb); 110. jp1=new JPanel(); 111. 112. add(jp1); 113. } 114. 115. //考试时候的组件布局 116. public void init2(){ 117. jp1.removeAll(); 118. //设置面板的布局为网格布局,只有一列 119. jp1.setLayout(new GridLayout(0,1)); 120. jlb=new JLabel("题目"); 121. jr1=new JRadioButton("1"); 122. jr2=new JRadioButton("2"); 123. jr3=new JRadioButton("3"); 124. jr4=new JRadioButton("4"); 125. 126. //单选按钮要实现互相排斥,多选一,ButtonGroup按钮组 127. bg=new ButtonGroup(); 128. bg.add(jr1); 129. bg.add(jr2); 130. bg.add(jr3); 131. bg.add(jr4); 132. jp2=new JPanel(); 133. jb1=new JButton("上一题"); 134. jb2=new JButton("下一题"); 135. jb3=new JButton("提交"); 136. jp2.add(jb1); 137. jp2.add(jb2); 138. jp2.add(jb3); 139. //中间的大面板jp1添加组件 140. //滚动条面板添加jlb 141. jp1.add(new JScrollPane(jlb)); 142. jp1.add(jr1); 143. jp1.add(jr2); 144. jp1.add(jr3); 145. jp1.add(jr4); 146. jp1.add(jp2); 147. 148. this.validate(); 149. 150. //单击上一题 151. jb1.addActionListener(new ActionListener() { 152. 153. @Override 154. public void actionPerformed(ActionEvent e) { 155. save(index); 156. //索引加一 157. index--; 158. printjm(index); 159. jb2.setEnabled(true); 160. if(index<1) { 161. jb1.setEnabled(false); 162. } 163. } 164. }); 165. 166. //单击下一题 167. jb2.addActionListener(new ActionListener() { 168. 169. @Override 170. public void actionPerformed(ActionEvent e) { 171. save(index); 172. //索引加一 173. index++; 174. printjm(index); 175. jb1.setEnabled(true); 176. if(index>list.size()-2) { 177. jb2.setEnabled(false); 178. } 179. } 180. }); 181. //提交试卷,给出成绩并写入record表 182. jb3.addActionListener(new ActionListener() { 183. 184. @Override 185. public void actionPerformed(ActionEvent e) { 186. //保存当前选项 187. save(index); 188. //比对用户答案和正确答案是否相同 189. int sum = 0; 190. //遍历集合的所有元素,取出两个成绩,比对 191. for(int i=0;i<list.size();i++) { 192. // System.out.println(list.get(i).getUserda()); 193. if(list.get(i).getUserda().equals(list.get(i).getAnswer())) { 194. sum+=10; 195. } 196. } 197. //给出用户名 198. String name=JOptionPane.showInputDialog("请输入你的名字"); 199. //成绩通过消息框显示 200. JOptionPane.showMessageDialog(null, "同学,你的成绩是"+sum+"分"); 201. //将用户名和成绩存入record表 202. //将用户名和成绩存入一个record对象中 203. Record re = new Record(); 204. re.setName(name); 205. re.setScore(sum); 206. //调用方法addrecord写数据 207. RecordDao.addrecord(re); 208. } 209. }); 210. } 211. 212. /** 213. * 统一设置字体,父界面设置之后,所有由父界面进入的子界面都不需要再次设置字体 214. */ 215. private static void InitGlobalFont(Font font) { 216. FontUIResource fontRes = new FontUIResource(font); 217. for (Enumeration<Object> keys = UIManager.getDefaults().keys(); keys.hasMoreElements();) { 218. Object key = keys.nextElement(); 219. Object value = UIManager.get(key); 220. if (value instanceof FontUIResource) { 221. UIManager.put(key, fontRes); 222. } 223. } 224. } 225. //显示索引为index的试题信息到界面中(jp1) 226. public void printjm(int index) { 227. //获取index下标的元素 228. test=list.get(index); 229. //将题目信息放到标签中,题号1-10 230. jlb.setText(index + 1 +"." + test.getContent()); 231. //将当前题的选项放到单选按钮中 232. jr1.setText(test.getSa()); 233. jr2.setText(test.getSb()); 234. jr3.setText(test.getSc()); 235. jr4.setText(test.getSd()); 236. //获取用户选择的答案内容 237. String userda=test.getUserda(); 238. if(userda!=null) { 239. //根据用户输入的答案,设置相应的单选按钮为选中状态 240. switch(userda) { 241. case"A":jr1.setSelected(true);break; 242. case"B":jr2.setSelected(true);break; 243. case"C":jr3.setSelected(true);break; 244. case"D":jr4.setSelected(true);break; 245. } 246. } 247. //界面刷新 248. validate(); 249. } 250. public void save(int index) { 251. //如果用户没有选择 252. String userda="E"; 253. //判断用户选的是哪一项 254. if(jr1.isSelected()) userda="A"; 255. if(jr2.isSelected()) userda="B"; 256. if(jr3.isSelected()) userda="C"; 257. if(jr4.isSelected()) userda="D"; 258. //用户答案写入 259. test.setUserda(userda); 260. //更新集合中对应的元素 261. list.set(index,test); 262. //按钮组所有选项清空 263. bg.clearSelection(); 264. } 265. 266. public static void main(String[] args) { 267. new ExamJFrame(); 268. } 269. }