秒表计时器——Java基础练手项目(Java课程设计)

前言:鄙人是大二在读学生,大二上学期Java课程设计选了一个秒表计时器的题目,在此把代码和心得分享出来(懒人可以直接看PPT)。鄙人资历尚浅,代码中会有许多不当之处,望各位大佬海涵,有更好的建议希望各位大佬留言评论区。

题目要求

设计一个与手机秒表类似的计时器,以钟表图形的方式呈现。

  1. 当用户用鼠标单击界面的“开始”按钮或图标时,秒表开始计时,表及数字都自动发生变化;当用户再次点击按钮,秒表暂停计时,按钮字样变为“继续”;当用户用鼠标点击“继续”按钮,秒表继续计时。
  2. 界面上还有一个“复位”按钮,当未点击“开始”按钮,没有进入计时状态时,“复位”按钮为灰色不可选,当开始计时后,“复位”按钮变为可选状态,当用户点击复位按钮时,秒表计时清零。

设计思路

  •   首先利用java中的swing创建窗口,及其相关的组件,构造出大概的图像,如下图
  • 然后利用java中的计时器类(Timer),让指针随着时间转动(本来有视频演示的,但是奈何视频鄙人还不会插入……)
  • 接着声明一些变量(例如haveStart,isStop,number)来帮助判断秒表的状态(如下图)

  • 结合静态变量,给三个按钮添加事件监听(jp_*为第*个按钮)

//手动换行分开三个按钮(手动滑稽)

//手动换行分开三个按钮(手动滑稽)

  • 使用jdbc技术连接java程序和mysql数据库(这个题目里面是没有要求的,但是想着完美一点就加上去了,下面3张图为代码演示和结果演示)

//手动换行分开图片(手动滑稽)

//手动换行分开图片(手动滑稽),下面这张图是数据库存储后的结果,为了方便展示直接使用了数据库管理系统的可视化工具navicat

程序分析

程序能够符合题目的所有要求,并且结合实际考虑,在题目要求之外添加了如下几个功能:

  1. 在未点击开始按钮时,暂停按钮也设置成灰色不可点击的状态
  2. 在未点击开始前,点击暂停或者复位按钮的话,会有弹窗提醒,告诉使用者“程序未开始,此按钮不可选!”
  3. 在窗口右侧添加了多行文本域,可以展示在一次使用中的多次记录的次序和时长
  4. 使用了JDBC技术连接了java程序和mysql数据库,可以在点击复位按钮时自动把每次记录的次序,时长,记录的时间存入数据库中,便于数据的保存和查询。

程序的不足之处:

  1. 因为采用了Java Swing中的组件来构造钟表,所以钟表图形简陋,窗口上的单行文本域和多行文本域也显得有些呆滞

心得与体会

在这个课程设计中遇到的难题及其解决方案:

1. 导包错误

这个课程设计中使用到了java中的计时器类(Timer),但是由于之前没有接触过这个类,所以是通过一些视频,及百度才知道了这个类,使用这个类是需要导包的,但是不止一个包含有这个类,当时我下意识的导了java.swing这个包,因为这个课程设计很多都用到了swing,导致程序报错(见下图),但是明明我和百度和视频上的几乎一模一样,在漫长的折磨下,我才想到可能是导错包了。

解决方案:在java的API文档和百度搜索上比较详细的了解了这个类在不同包下的使用之后,挑选了一个比较合适的包导入,并且修改java语句,尝试完成自己让指针转动的需求

2.版本不匹配问题  

我在电脑上配置的mysql的版本是5.7.36,然后用到的jdbc的jar是最新的8.0.27版本的,所以在起初看视频学习jdbc技术时,敲着一模一样的代码,但是我这里会报错(见下图),这就让人十分苦恼,难以继续学习下去    

 

解决方案:在官网上找到对应版本的jdbc的jar文件(即5.7.36版本的jdbc的jar文件),然后把这个文件配置到运行环境中

几个有用的网址:

1. Overview - Java 11中文版 - API参考文档

Java中文在线帮助文档

2.https://mvnrepository.com/artifact/mysql/mysqlconnector-java

可以很容易获取Jdbc中任意版本的jar包

3. 百度一下,你就知道

可以解答我们目前为止在编程上遇到的90%的问题

源码

package Miaobiao;

import javax.swing.*;
import java.awt.event.*;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.awt.*;
import java.util.*;
import java.util.Date;
import java.util.Timer;


public class MiaoBiao {
      //获得记录的时间
      SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss ");
      Date date = new Date(System.currentTimeMillis());
      String s;
    // 创造各个组件
    final static double pai = 3.14159;
    JFrame jf = new JFrame("秒表窗口");
    JPanel jp_one = new JPanel();
    JPanel jp_two = new JPanel();
    JPanel jp_three = new JPanel();
    static int location_x = 0;
    static int location_y = 110;
    static MyCanvas myCanvas = new MyCanvas();

    JButton jb_one = new JButton("开始");
    JButton jb_two = new JButton("暂停");
    JButton jb_three = new JButton("复位");
    // 未开始时点击复位弹出的对话框
    JDialog jd = new JDialog(jf, true);
    JTextArea jta = new JTextArea("程序未开始,此按钮不可选!");

    static JTextField tf = new JTextField(10);
    JTextArea ta = new JTextArea(30, 10);
    // 设置一个变量来观察秒表是否暂停
    static boolean isStop = true;
    // 设置一个变量记录时间
    static private int t = 0;
    // 设置一个变量是否开始
    static boolean haveStart = false;
    // 设置一个变量记录秒表运行次数
    static int number = 0;
    

    private static class MyTimer extends TimerTask {

        @Override
        public void run() {
            if (isStop) {

            } else {
            	//更新指针终点的x,y坐标,并且更新单行文本域的内容
                t++;
                location_x = (int) (Math.cos((pai / 2 - t * pai / 30)) * 110);
                location_y = (int) (Math.sin((pai / 2 - t * pai / 30)) * 110);
                tf.setText("" + t + "秒");
                myCanvas.repaint();
               
            }
            // TODO Auto-generated method stub

        }

    }
  /*  void  Jdbc() throws SQLException
    {  
    	Driver driver =new com.mysql.jdbc.Driver();
    	String url="jdbc:mysql://localhost:3306/miaobiao";
    	Properties info =new Properties();
    	info.setProperty("user", "root");
    	info.setProperty("password", "root");
    	Connection conn=driver.connect(url, info);
    	String sql="insert into record(number,time,date) values(?,?,?)";
    	PreparedStatement ps=conn.prepareStatement(sql);
    	ps.setInt(1, number);
    	ps.setString(2, t+"秒");
    	ps.setString(3,s);
    	ps.execute();
    	ps.close();
    	conn.close();
    }*/
    // 组装函数
    public void init() {
        // 设置弹窗内容
        jd.setBounds(300, 300, 300, 200);
        jd.setTitle("错误!");
        jd.add(jta);
        // jd.setTe
        // 给复位按钮设置成灰色
        jb_two.setBackground(Color.gray);
        jb_three.setBackground(Color.gray);
        // 给按钮添加事件监听
        jb_one.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (jb_two.getActionCommand().equals("暂停")) {
                    isStop = false;
                    haveStart = true;
                    jb_two.setBackground(new Color(236, 242, 248));
                    jb_three.setBackground(new Color(236, 242, 248));
                }
            }
        });
        jb_two.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // 判断这个按钮当前的状态
                if (!haveStart && e.getActionCommand().equals("暂停")) {
                    jd.setVisible(true);
                } else if (haveStart && e.getActionCommand().equals("暂停")) {
                    isStop = true;
                    jb_two.setText("继续");
                } else {
                    isStop = false;
                    jb_two.setText("暂停");
                }

            }
        });
        jb_three.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (haveStart) {
                    // 更新成员变量的属性值
              
                    isStop = true;
                    haveStart = false;
                    location_x = 0;
                    location_y = 110;
                    jb_two.setText("暂停");
                    // 在右边的文本域中更新内容
                    ta.append("第" + (++number )+ "次:" + t + "秒" + "\n");
                    //写入数据库
  	           /* try {
                		date = new Date(System.currentTimeMillis());
                		s=formatter.format(date);
						Jdbc();
					} catch (SQLException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}*/
                    t = 0;
                    tf.setText("");
                    // 给两个按钮回复颜色
                    jb_three.setBackground(Color.gray);
                    jb_two.setBackground(Color.gray);
                    myCanvas.repaint();

                } else {
                    jd.setVisible(true);
                }
            }
        });
        // 给三个面板添加组件
        myCanvas.setSize(new Dimension(360, 360));
        //myCanvas.setBackground(Color.blue);
        jp_one.add(myCanvas);
        jp_one.add(tf);
        jp_two.add(jb_one);
        jp_two.add(jb_two);
        jp_two.add(jb_three);
        jp_three.add(ta);

        // 给窗口添加三个面板
        jf.add(jp_one, BorderLayout.CENTER);
        jf.add(jp_two, BorderLayout.SOUTH);
        jf.add(jp_three, BorderLayout.EAST);

        // 设置窗口位置,大小,可见性,添加窗口关闭监听
        jf.setBounds(200, 200, 500, 500);
        jf.setVisible(true);
        //jf.addWindowListener(new MyListener());
        jf.setDefaultCloseOperation(1);

        Timer timer = new Timer();
        timer.schedule(new MyTimer(), 0, 1000);

    }

    public static void main(String[] args) {
        new MiaoBiao().init();
    }

 

    // 创建画布
    private static class MyCanvas extends Canvas {
        @Override
        public void paint(Graphics g) {
            // 绘制钟表图
            g.drawOval(60, 40, 250, 250);
            g.setFont((new Font("Times", Font.BOLD, 30)));
            g.drawString("12", 170, 65);
            g.drawString("3", 290, 175);
            g.drawString("6", 178, 288);
            g.drawString("9", 62, 175);
            g.drawString("1", 235, 80);
            g.drawString("2", 275, 120);
            g.drawString("4", 275, 235);
            g.drawString("5", 235, 275);
            g.drawString("7", 126, 275);
            g.drawString("8", 80, 235);
            g.drawString("10", 75, 120);
            g.drawString("11", 115, 80);
            // 绘制指针,利用计时器更新 a b 的值使指针不停的转动
            int a = 185 + location_x;
            int b = 165 - location_y;
            g.drawLine(185, 165, a, b);

        }

    }
}

注:为了让代码能够成功运行,有关数据库部分的代码被注释了。(注释掉的部分:第67-83行,第133-140行)

另附本人的实验报告文档与分享会的PPT:

链接:https://pan.baidu.com/s/17FUTWmdxrha2Lpy8aARPyQ 
提取码:zlry

好了~第一篇博客到此就结束了,大家对这个课程设计有什么问题可以在评论区留言~也欢迎各位大佬提出宝贵的修改意见~

  • 30
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值