201871010102-常龙龙《面向对象程序设计(java)》第十六周学习总结
项目 |
内容 |
这个作业属于哪个课程 |
https://www.cnblogs.com/nwnu-daizh/ |
这个作业的要求在哪里 |
https://www.cnblogs.com/nwnu-daizh/p/12031970.html |
作业学习目标 |
(1) 掌握Java应用程序的打包操作; (2) 掌握线程概念; (3) 掌握线程创建的两种技术。
|
第一部分:总结第十二章本周理论知识(25分)
14.1 什么是线程
1.程序、进程与线程
● 程序是一段静态的代码,它是应用程序执行的蓝本。
● 进程是程序的一次动态执行,它对应了从代码加载、执行至执行完毕的一个完整过程。
● 线程是进程执行过程中产生的多条执行线索。 线程是比进程执行更小的单位。
2.Java中实现多线程应用有两种途径:
● 创建Thread类的子类
● 在程序中实现Runnable接口
14.1.1 用Thread类的子类创建线程
只需从Thread类派生出一个子类,在类中一定要实现run()。
例: class hand extends Thread {
public void run() {…….}
}
class Lefthand extends Thread {
public void run() {
for(int i=0;i<=5;i++)
{ System.out.println("You are Students!");
try{ sleep(500); }
catch(InterruptedException e) {… }
}
}
class Righthand extends Thread {
public void run() {
for(int i=0;i<=5;i++) {
System.out.println("I am a Teacher!");
try{ sleep(300); }
catch(InterruptedException e) {…. } }
}
}
● 然后用该类创建一个对象
Lefthand left=new Lefthand();
Righthand right=new Righthand();
● 用start()方法启动线程
left.start();
right.start();
● 在程序中实现多线程,关键性操作:
-定义用户线程操作,即run()方法的实现。
-在适当的时候启动线程。
public class ThreadTest {
static Lefthand left;
static Righthand right;
public static void main(String[] args) {
left=new Lefthand();
right=new Righthand();
left.start();
right.start();
}
}
例:ThreadTest.java 执行结果:
You are Students!
I am a Teacher!
I am a Teacher!
You are Students!
I am a Teacher!
I am a Teacher!
You are Students!
I am a Teacher!
You are Students!
I am a Teacher!
You are Students!
You are Students!
14.1.2 用Runnable()接口创建线程
●用Runnable()接口实现多线程时,也必须必须实现run()方法,也需用start()启动 线程。
●用Runnable()接口实现多线程时,常用Thread类的构造方法来创建线程对象。
class BallRunnable implements Runnable {
public void run() {
try { for (int i = 1; i <= STEPS; i++) {
ball.move(component.getBounds());
component.repaint();
Thread.sleep(DELAY);
}
}catch (InterruptedException e) { }
}
●API:java.lang.Thread
Thread(Runnable r)
Runnable r = new BallRunnable(b, comp);
Thread t = new Thread(r);
创建一个新线程,它调用r的run(), r是一个实现了Runnable接口的类的实例。
● 例14-1 Bounce.java p625
● 例14-4 BounceThread.java p631
14.2 中断线程
●当线程的run方法执行方法体中最后一条语句后,并经由执行return语句返回时,或者出现了在方法中没有捕获的异常时,线程将终止。
●在程序中常常调用interrupt()来终止线程,interrupt()不仅可中断正在运行的线程,而且也能中断处于blocked状态的线程,此时interrupt()会抛出一个InterruptedException异常。
●Java提供了几个用于测试线程是否被中断的方法。
●void interrupt() 向一个线程发送一个中断请求,同时把这个线程的“interrupted”状态置为true。 若该线程处于blocked状态,会抛出InterruptedException。
●static boolean interrupted() 检测当前线程是否已被中断,并重置状态“interrupted”值为false。
●boolean isInterrupted() 检测当前线程是否已被中断,不改变状态“interrupted”值 。
14.3 线程状态
线程一共有如下6种状态:
●New (新建)
●Runnable (可运行)
●Blocked (被阻塞)
●Waiting (等待)
●Timed waiting (计时等待)
●Terminated (被终止)
14.3.1 新创建线程
●new(新建)
线程对象刚刚创建,还没有启动,此时还处于不可运行状态。
●Thread thread=new Thread(“test”)
此时线程thread处于新建状态,但已有了相应的内存空间以及其它资源。
14.3.2 被终止的线程
●Terminated (被终止)
线程被终止的原因有二:
一是run()方法中最后一个语句执行完毕,因而自然死亡。
二是因为一个没有捕获的异常终止了run方法,从而意外死亡。
●thread.stop() 可以调用线程的stop方法杀死一个线程,但是,stop方法已过时,不要在自己的代码中调用它。
第二部分:实验部分
实验1: 导入第13章示例程序,测试程序并进行代码注释。
测试程序1
● 在elipse IDE中调试运行教材585页程序13-1,结合程序运行结果理解程序;
● 将所生成的JAR文件移到另外一个不同的目录中,再运行该归档文件,以便确认程序是从JAR文件中,而不是从当前目录中读取的资源。
● 掌握创建JAR文件的方法;
代码如下:
package resource; import java.awt.*; import java.io.*; import java.net.*; import java.util.*; import javax.swing.*; /** * @version 1.41 2015-06-12 * @author Cay Horstmann */ public class ResourceTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new ResourceTestFrame(); frame.setTitle("ResourceTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } /** * 一个加载图像和文本资源的框架。 */ class ResourceTestFrame extends JFrame { private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 300; public ResourceTestFrame() { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); //在找到ResourceTest类的地方查找about.gif文件 URL aboutURL = getClass().getResource("about.gif"); //将此图像设置为框架的图标 Image img = new ImageIcon(aboutURL).getImage(); setIconImage(img); JTextArea textArea = new JTextArea(); //getResourceAsStream方法的作用是找到与类位于同一位置的资源,返回一个可以加载资源的URL或者输入流 InputStream stream = getClass().getResourceAsStream("about.txt"); //在读取文本时使用同一编码UTF-8 try (Scanner in = new Scanner(stream, "UTF-8")) { while (in.hasNext()) textArea.append(in.nextLine() + "\n"); } add(textArea); } }
生成jar文件的过程:通过Eclipse中的功能 File->Export->Java->JAR File->选择需要生成jar文件的包->选择jar文件存储位置JAR file->next->next->main class->finish
生成的文件归档后使用压缩包打开:
双击运行结果如下:
测试程序2:
● 在elipse IDE中调试运行ThreadTest,结合程序运行结果理解程序;
● 掌握线程概念;
● 掌握用Thread的扩展类实现线程的方法;
● 利用Runnable接口改造程序,掌握用Runnable接口创建线程的方法。
代码如下:
package ThreadTest; class Lefthand extends Thread { public void run() { for(int i=0;i<=5;i++) { System.out.println("You are Students!"); //调用Thread的sleep方法不会创建一个新线程, //sleep是Thread的静态方法,用于暂停当前线程的活动 try{ sleep(500); } catch(InterruptedException e) { System.out.println("Lefthand error."); } } } } class Righthand extends Thread { public void run() { for(int i=0;i<=5;i++) { System.out.println("I am a Teacher!"); try{ sleep(300); } catch(InterruptedException e) { System.out.println("Righthand error."); } } } } public class ThreadTest { static Lefthand left; static Righthand right; public static void main(String[] args) { left=new Lefthand(); right=new Righthand(); //同时启动两个线程 left.start(); right.start(); } }
运行结果如下:
测试程序3:
● 在Elipse环境下调试教材625页程序14-1、14-2 、14-3,结合程序运行结果理解程序;
● 在Elipse环境下调试教材631页程序14-4,结合程序运行结果理解程序;
● 对比两个程序,理解线程的概念和用途;
● 掌握线程创建的两种技术。
代码一:
Ball类:
package bounce; import java.awt.geom.*; /** * 在长方形边缘上移动和反弹的球 * @version 1.33 2007-05-17 * @author Cay Horstmann */ public class Ball { private static final int XSIZE = 15; private static final int YSIZE = 15; private double x = 0; private double y = 0; private double dx = 1; private double dy = 1; /** * 将球移动到下一个位置,如果碰到其中一个边,则反转方向 */ public void move(Rectangle2D bounds) { x += dx; y += dy; //宽度上的最小位置 if (x < bounds.getMinX()) { x = bounds.getMinX(); dx = -dx; } //宽度上的最大位置 if (x + XSIZE >= bounds.getMaxX()) { x = bounds.getMaxX() - XSIZE; dx = -dx; } //高度上的最小位置 if (y < bounds.getMinY()) { y = bounds.getMinY(); dy = -dy; } //宽度上的最大位置 if (y + YSIZE >= bounds.getMaxY()) { y = bounds.getMaxY() - YSIZE; dy = -dy; } } /** * 获取球在其当前位置的形状 */ public Ellipse2D getShape() { return new Ellipse2D.Double(x, y, XSIZE, YSIZE); } }
BallComponent类:
package bounce; import java.awt.*; import java.util.*; import javax.swing.*; /** * 画弹力球的部件. * @version 1.34 2012-01-26 * @author Cay Horstmann */ public class BallComponent extends JPanel { private static final int DEFAULT_WIDTH = 450; private static final int DEFAULT_HEIGHT = 350; private java.util.List<Ball> balls = new ArrayList<>(); /** * 增加一个球到组件上。 * @param b the ball to add */ //创建add方法,在add方法中使用球类型集合的add方法向集合中添加球 public void add(Ball b) { balls.add(b); } //paintComponent方法中有一个Graphics类型的参数,这个参数保留着用于绘制图像和文本的设置。 //在Java中,所有的绘制都必须使用Graphics对象,其中包含了绘制图案,图像和文本的方法。 public void paintComponent(Graphics g) { super.paintComponent(g); // 使用背景色绘制面板 Graphics2D g2 = (Graphics2D) g; //获取每一个球的位置和形状并使用默认颜色进行填充 for (Ball b : balls) { g2.fill(b.getShape()); } } public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } }
Bounce类:
package bounce; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * 显示动画弹跳球。 * @version 1.34 2015-06-21 * @author Cay Horstmann */ public class Bounce { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new BounceFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } /** * 有球部件和按钮的框架。 */ class BounceFrame extends JFrame { private BallComponent comp; public static final int STEPS = 1000; public static final int DELAY = 3; /** * 构造包含用于显示弹跳球和启动和关闭按钮的框架 */ public BounceFrame() { setTitle("Bounce"); comp = new BallComponent(); add(comp, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(); //使用addBuuton方法为按钮添加标题,监听器,并且将按钮添加至面板中 addButton(buttonPanel, "Start", event -> addBall()); addButton(buttonPanel, "Close", event -> System.exit(0)); //将按钮面板添加至框架的南部 add(buttonPanel, BorderLayout.SOUTH); pack(); } /** *向容器添加按钮 * @param c the container * @param 为按钮设置标题 * @param 为按钮设置监听器 */ public void addButton(Container c, String title, ActionListener listener) { JButton button = new JButton(title); c.add(button); button.addActionListener(listener); } /** * 在面板中添加一个弹跳球,使其弹跳1000次。 */ public void addBall() { try { Ball ball = new Ball(); comp.add(ball); for (int i = 1; i <= STEPS; i++) { //这样设置的话所有球的移动都处于一个线程当中 ball.move(comp.getBounds()); comp.paint(comp.getGraphics()); Thread.sleep(DELAY); } } //中断异常 catch (InterruptedException e) { } } }
运行结果如下:
代码二:
Ball类:
package bounce; import java.awt.geom.*; /** * 在长方形边缘上移动和反弹的球 * @version 1.33 2007-05-17 * @author Cay Horstmann */ public class Ball { private static final int XSIZE = 15; private static final int YSIZE = 15; private double x = 0; private double y = 0; private double dx = 1; private double dy = 1; /** * 将球移动到下一个位置,如果碰到其中一个边,则反转方向 */ public void move(Rectangle2D bounds) { x += dx; y += dy; //宽度上的最小位置 if (x < bounds.getMinX()) { x = bounds.getMinX(); dx = -dx; } //宽度上的最大位置 if (x + XSIZE >= bounds.getMaxX()) { x = bounds.getMaxX() - XSIZE; dx = -dx; } //高度上的最小位置 if (y < bounds.getMinY()) { y = bounds.getMinY(); dy = -dy; } //宽度上的最大位置 if (y + YSIZE >= bounds.getMaxY()) { y = bounds.getMaxY() - YSIZE; dy = -dy; } } /** * 获取球在其当前位置的形状 */ public Ellipse2D getShape() { return new Ellipse2D.Double(x, y, XSIZE, YSIZE); } }
BallComponent类:
package bounce; import java.awt.*; import java.util.*; import javax.swing.*; /** * 画弹力球的部件. * @version 1.34 2012-01-26 * @author Cay Horstmann */ public class BallComponent extends JPanel { private static final int DEFAULT_WIDTH = 450; private static final int DEFAULT_HEIGHT = 350; private java.util.List<Ball> balls = new ArrayList<>(); /** * 增加一个球到组件上。 * @param b the ball to add */ //创建add方法,在add方法中使用球类型集合的add方法向集合中添加球 public void add(Ball b) { balls.add(b); } //paintComponent方法中有一个Graphics类型的参数,这个参数保留着用于绘制图像和文本的设置。 //在Java中,所有的绘制都必须使用Graphics对象,其中包含了绘制图案,图像和文本的方法。 public void paintComponent(Graphics g) { super.paintComponent(g); // 使用背景色绘制面板 Graphics2D g2 = (Graphics2D) g; //获取每一个球的位置和形状并使用默认颜色进行填充 for (Ball b : balls) { g2.fill(b.getShape()); } } public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } }
BounceThread类:
package bounceThread; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * 显示动画弹跳球。 * @version 1.34 2015-06-21 * @author Cay Horstmann */ public class BounceThread { public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame frame = new BounceFrame(); frame.setTitle("BounceThread"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } /** * 有面板和按钮的框架。 */ class BounceFrame extends JFrame { private BallComponent comp; public static final int STEPS = 1000; public static final int DELAY = 5; /** * 构造包含用于显示弹跳球和开始和关闭按钮的组件的框架 */ public BounceFrame() { comp = new BallComponent(); add(comp, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(); addButton(buttonPanel, "Start", event -> addBall()); addButton(buttonPanel, "Close", event -> System.exit(0)); add(buttonPanel, BorderLayout.SOUTH); pack(); } /** * 添加一个按钮到框架中. * @param c the container * @param 为按钮设置标题 * @param 为按钮设置监听器 */ public void addButton(Container c, String title, ActionListener listener) { JButton button = new JButton(title); c.add(button); button.addActionListener(listener); } /** * 在画布上添加一个弹跳球并开始一条线使其弹跳 */ public void addBall() { Ball ball = new Ball(); comp.add(ball); //将移动球的代码放置在一个独立的线程中,运行这段代码可以提高弹跳球的相应性能 //实现一个BallRunnable类,然后,将动画代码放在run方法中,这样就即将动画代码放在了一个单独的线程中 Runnable r = () -> { try { for (int i = 1; i <= STEPS; i++) { ball.move(comp.getBounds()); //调用组件的repaint方法,重新绘制组件 comp.repaint(); Thread.sleep(DELAY); } } catch (InterruptedException e) { } }; //将Runnable对象作为入口参数传入Thread的构造函数,再调用start方法就可以启动线程 Thread t = new Thread(r); t.start(); } }
运行结果如下:
可以同时运行一个以上线程的程序叫多线程程序。
实验2:结对编程练习:采用GUI界面设计以下程序,并创建程序归档文件。
● 设计一个100以内整数小学生四则运算练习程序,由计算机随机产生10道加减乘除练习题,
学生输入答案,由程序检查答案是否正确,每道题正确计10分,错误不计分,10道题测试结束后给出测试总分;
● 将程序中测试练习题及学生答题结果输出到文件,文件名为test.txt。
1) 程序设计思路简述;
GUI界面设计思路:
我在框架北部加了一个title(JLabel),在中部加了一个problemPanel面板,problemPanel面板布局为10行一列的网格布局,每一行又是一个contentPanel面板,在contentPanel面板中添加了显示题号的orderLabel,显示题目的problemLabel,用于作答的answer,显示对错的judgeLabel组件。在框架南部加了一个用于放置按钮的buttonPanel面板,里面分别放置makeProblemButton,submitbutton,reset
Button和checkButton。另外还有一个用于显示txt文本的框架,其中只放置了一个display(JTextArea),最后,我加了一个计时器来限制作答时间(额外补充的)。这样,就完成了整个小学生四则运算练习程序的GUI页面布局。
动作事件设计思路:我为出题按钮设置了一个problemAction监听器,监听器中又有一个makeOperation方法,用于生成题目,makeOperation方法中使用随机数产生两个操作数(第二个操作数过滤掉0),然后再产生一个1-4的随机数用于设置题目的类型,将生成的题目设置为problemLabel的标题,再将每个题的结果存在result数组中。同时为提交按钮设置了一个judgeAction监听器,将answer中输入的内容与result所存的结果相比较,想同judgeLabel则显示√,否则显示×。并为重置按钮设置resetAction监听器,将answer中输入的内容全部清空,但是不能在提交之后清空。最后为check按钮设置checkAction监听器,将所有信息读入txt文件,并且创建新框架,在新框架中显示出最后的信息。在倒计时动作事件中,我使用time类中的schedule方法实现了倒计时的功能,并且在时间剩余10秒时,字体会放大以用于强调,当时间到0时,会弹出信息对话框,并且当用户提交时,计时也会停止。
2) 符合编程规范的程序代码;
ArithmeticExercisesFrame类:
package demo; import java.awt.BorderLayout; import java.awt.Color; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.util.Random; import java.util.Timer; import java.util.TimerTask; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; public class ArithmeticExercisesFrame extends JFrame { private JPanel[] contentPanel=new JPanel[10]; private JLabel[] orderLabel=new JLabel[10]; private JLabel[] problemLabel=new JLabel[10]; private JTextField[] answer=new JTextField[10]; private JLabel[] judge=new JLabel[10]; private JPanel problemPanel; private JButton submitButton; private JButton resetButton; private JPanel buttonPanel; private JLabel title; private JButton makeproblemButton; private int operands1; private int operands2; private int[] result=new int[10]; private JButton checkButton; //private static int i=1; private File file=new File("小学生四则运算答案结果"); private JTextArea textarea=new JTextArea(10,20); private JPanel timeLimitPanel; private JLabel sumTime; private JLabel timeLabel; private JLabel timechange; private JLabel s; private Timer time; private JOptionPane message; public ArithmeticExercisesFrame() { setSize(400,630); //添加标题 JPanel titlePanel=new JPanel(); title = new JLabel("小学生四则运算练习程序"); title.setFont(new Font("宋体",Font.ROMAN_BASELINE,25)); titlePanel.add(title); add(titlePanel,BorderLayout.NORTH); problemPanel = new JPanel(); problemPanel.setLayout(new GridLayout(11,1)); time(); createQuestionBoard(); addQuestionBoard(); makeButtonPanel(); add(problemPanel,BorderLayout.CENTER); } public void time() { timeLimitPanel = new JPanel(); sumTime = new JLabel("总时间:180s"); timeLabel = new JLabel(" 倒计时:"); timechange = new JLabel("180"); s = new JLabel("s"); sumTime.setFont(new Font("宋体",Font.ROMAN_BASELINE,20)); sumTime.setForeground(Color.green); timeLabel.setFont(new Font("宋体",Font.ROMAN_BASELINE,20)); timeLabel.setForeground(Color.red); timechange.setFont(new Font("宋体",Font.ROMAN_BASELINE,20)); timechange.setForeground(Color.red); s.setFont(new Font("宋体",Font.ROMAN_BASELINE,20)); s.setForeground(Color.red); timeLimitPanel.add(sumTime); timeLimitPanel.add(timeLabel); timeLimitPanel.add(timechange); timeLimitPanel.add(s); problemPanel.add(timeLimitPanel); } public void createQuestionBoard() { //为每一行创建一个面板 for(int i=0;i<10;i++) { contentPanel[i]=new JPanel(); contentPanel[i].setLayout(new FlowLayout(FlowLayout.CENTER,15,0)); } orderLabel = new JLabel[] { new JLabel("第一题:"), new JLabel("第二题:"), new JLabel("第三题:"), new JLabel("第四题:"), new JLabel("第五题:"), new JLabel("第六题:"), new JLabel("第七题:"), new JLabel("第八题:"), new JLabel("第九题:"), new JLabel("第十题:") }; for(int i=0;i<10;i++) { problemLabel[i]=new JLabel("请出题"); answer[i]=new JTextField(8); judge[i]=new JLabel("待定"); judge[i].setFont(new Font("宋体",Font.ROMAN_BASELINE,30)); } } public void addQuestionBoard() { for(int i=0;i<contentPanel.length;i++) { contentPanel[i].add(orderLabel[i]); contentPanel[i].add(problemLabel[i]); contentPanel[i].add(answer[i]); contentPanel[i].add(judge[i]); problemPanel.add(contentPanel[i]); } } public void makeButtonPanel() { buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER,10,0)); makeproblemButton = new JButton("出题"); submitButton=new JButton("提交"); resetButton=new JButton("重置"); checkButton = new JButton("查看"); buttonPanel.add(makeproblemButton); buttonPanel.add(submitButton); buttonPanel.add(resetButton); buttonPanel.add(checkButton); ActionListener problem=new problemAction(); ActionListener countDown=new timeAction(); makeproblemButton.addActionListener(problem); makeproblemButton.addActionListener(countDown); ActionListener judge=new judgeAction(); submitButton.addActionListener(judge); ActionListener reset=new resetAction(); resetButton.addActionListener(reset); ActionListener check=new checkAction(); checkButton.addActionListener(check); add(buttonPanel,BorderLayout.SOUTH); } //产生加减乘除运算的方法 public void makeOperation() { for(int i=0;i<10;i++) { Random rand=new Random(); int temp; operands1 = rand.nextInt(100) +1; operands2=rand.nextInt(100) +1; while(operands2==0) { operands2=rand.nextInt(100) +1; } int index=rand.nextInt(4) +1; switch(index) { case 1:problemLabel[i].setText(operands1+"+"+operands2); result[i] = operands1+operands2; break; case 2:problemLabel[i].setText(operands1+"-"+operands2); result[i]=operands1-operands2; break; case 3:problemLabel[i].setText(operands1+"*"+operands2); result[i]=operands1*operands2; break; case 4:problemLabel[i].setText(operands1+"/"+operands2); result[i]=operands1/operands2; break; default:System.out.println("error!"); } } } //判断对错的方法 public void judgeProblem() { int score=0; for(int i=0;i<10;i++) { //System.out.println(result[i]); int res=Integer.parseInt(answer[i].getText()); //System.out.println(res); if(res==result[i]) { judge[i].setText("√"); judge[i].setForeground(Color.green); score+=10; } else { judge[i].setText("×"); judge[i].setForeground(Color.red); score+=0; } textarea.append(orderLabel[i].getText()+" "+problemLabel[i].getText()+" "+"你的答案:"+answer[i].getText()+" 正确答案:"+result[i]+"\n"); } textarea.append("你的总得分是:"+score+"\n"); } public void savefile() { try { FileWriter fw=new FileWriter(file); //System.out.println(textarea.getText()); fw.write(textarea.getText()); fw.close(); }catch (FileNotFoundException e) { System.out.println("信息文件找不到"); e.printStackTrace(); } catch (IOException e) { System.out.println("信息文件读取错误"); e.printStackTrace(); } } //出题监听器 class problemAction implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { makeOperation(); for(int i=0;i<10;i++) { judge[i].setVisible(false); answer[i].setText(null); } } } //判断正误监听器 class judgeAction implements ActionListener { @Override public void actionPerformed(ActionEvent e) { judgeProblem(); savefile(); for(int i=0;i<10;i++) { judge[i].setVisible(true); } time.cancel(); } } //查看结果监听器 class checkAction implements ActionListener { @Override public void actionPerformed(ActionEvent e) { EventQueue.invokeLater(() -> { var frame = new checkFrame(); frame.setTitle("小学生四则运算答案结果"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } //重置监听器 class resetAction implements ActionListener { @Override public void actionPerformed(ActionEvent e) { for(int i=0;i<10;i++) { if(!judge[i].isVisible()) { answer[i].setText(null); } } } } //倒计时监听器 class timeAction implements ActionListener{ private int i=180; @Override public void actionPerformed(ActionEvent e) { time = new Timer(); time.schedule(new TimerTask() { public void run() { timechange.setText(""+(i--)); if(i<=10) { timechange.setFont(new Font("宋体",Font.ROMAN_BASELINE,30)); } if(i<0) { time.cancel(); message.showMessageDialog(ArithmeticExercisesFrame.this,"同学,考试时间已结束,请立即停止作答!"); for(int i=0;i<10;i++) { answer[i].setEditable(false); } } } }, 0, 20); } } }
checkFrame类:
package demo; import java.awt.BorderLayout; import java.awt.Font; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import javax.swing.JFrame; import javax.swing.JTextArea; public class checkFrame extends JFrame { private JTextArea display; private File file; //private static int i=1; public checkFrame() { setSize(400,600); display = new JTextArea(10,20); add(display,BorderLayout.CENTER); loadfile(); } public void loadfile() { try { file=new File("小学生四则运算答案结果"); FileInputStream fis = new FileInputStream(file); BufferedReader in = new BufferedReader(new InputStreamReader(fis)); String temp = null; display.append(" 小学生四则运算答案结果"+"\n"); while((temp=in.readLine())!=null) { display.append(temp+"\n"); } display.setFont(new Font("宋体",Font.ROMAN_BASELINE,15)); in.close(); }catch (FileNotFoundException e) { System.out.println("信息文件找不到"); e.printStackTrace(); } catch (IOException e) { System.out.println("信息文件读取错误"); e.printStackTrace(); } } }
ArithmeticExercisesFrameTest类:
package demo; import java.awt.*; import javax.swing.*; /** * @version 1.35 2018-04-10 * @author Cay Horstmann */ public class ArithmeticExercisesFrameTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { var frame = new ArithmeticExercisesFrame(); frame.setTitle("小学生四则运算练习程序"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } }
3) 程序运行功能界面截图;
4) 结对过程描述,提供两人在讨论、细化和编程时的结对照片(非摆拍)。
5)程序归档文件
实验总结:(15分)
通过本章的第一个测试程序,我掌握了Java应用程序的打包操作,按我的理解是,如果将Java应用程序打包之后就可以直接发给其他人,而那个人就可以在安装了java虚拟机的计算机上直接运行此应用程序,大大加大了应用程序的可移植性。通过第三个测试程序,我掌握了线程创建的两种技术。在结对编程中,一些不懂的知识点我也通过上网查询慢慢掌握了,最终的编程效果我还是比较满意的,但是程序还是有可提高的余地,我会继续努力,将此程序不断完善,并在此过程中掌握更多的API以及编程技巧。