【问题标题】:Java Thread - Make a clock and own clockJava Thread - 制作时钟和自己的时钟
【发布时间】:2025-12-06 15:30:01
【问题描述】:

所以我开始对 Threads 及其工作原理产生了浓厚的兴趣,它的工作原理有点令人惊奇,但我今天才了解它并试图让一个程序工作。所以我试图制作一个时钟,在 Jlabel 中为我提供一个当前时钟,以及一个我自己输入时间的文本字段。所以我想做的是它应该首先向我显示时间,当按下“设置时间”按钮时,它应该改变我输入的时间并从那里作为时钟。

所以我现在的问题是,每当我按下设置时间时,它会改变一秒钟,然后再次返回当前时钟。而且我真的不知道如何在按下设置时间时停止第一个线程(启动第二个线程)

不过,我认为这有点简单但使用起来很有趣,

编辑:我还发现输入自己的“时钟”时计数会出现问题。我的代码:

 public Clock() {
            initialize();
            Thread1();

        }

    .......


JButton btnSetTime = new JButton("Set time");
            btnSetTime.setBounds(474, 262, 89, 23);
            frame.getContentPane().add(btnSetTime);
            btnSetTime.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    if(e.getSource() == btnSetTime) {
                        Thread2();

                    }

                }
            });
        }

        public void Thread2() {
            Thread t2 = new Thread() {
                public void run() {
                    try {
                        for(;;) {
                            int hour = Integer.parseInt(tfhour.getText());
                            int minute = Integer.parseInt(tfminute.getText());
                            int second = Integer.parseInt(tfsecond.getText());

                            lblKlockan.setText(hour + ":" + minute + ":" + second);
                            sleep(1000);
                        }
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } 
                }
            };t2.start();
        }

        public void Thread1() {
            Thread t1 = new Thread() {
                public void run() {
                    try {
                        for(;;) {
                            Calendar cal = Calendar.getInstance();
                            int hour = cal.get(Calendar.HOUR_OF_DAY);
                            int minute = cal.get(Calendar.MINUTE);
                            int second = cal.get(Calendar.SECOND);

                            lblKlockan.setText(hour + ":" + minute + ":" + second);
                            sleep(1000);
                        }
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } 
                }
            };t1.start();
        }
    }

如我所见,int hour = Integer.parseInt(tfhour.getText());如果我是对的,如果我稍后改成自己的时钟,可能不会算作时钟?在这种情况下,我该如何解决?

我希望我的所有问题都在这里,我希望这里的任何人也愿意帮助我:)

编辑:

为了方便查看:

编辑部分 3:0

【问题讨论】:

    标签: java multithreading user-interface


    【解决方案1】:

    当线程 2 启动时,您必须定义一个全局变量来停止线程 1。这是一个例子,

    //define a variable that controls the thread 1
    static boolean clockSet = false;
    

    现在线程 1 被写入,例如它仅在 clockSet 为 false 时运行,即时钟不是通过单击设置的。

      Thread t1 = new Thread(){
            public void run(){
               while(!clockSet){
                Calendar cal = Calendar.getInstance();
                    int hour = cal.get(Calendar.HOUR_OF_DAY);
                    int minute = cal.get(Calendar.MINUTE);
                    int second = cal.get(Calendar.SECOND);                   
                   lblKlockan.setText(hour + ":" + minute + ":" + second);
                   try {
                  sleep(1000);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
            }
        }
       };
    

    在您的线程 2 中,将 clockSet 设置为 true,因此线程 1 将停止。我看到您只是显示输入的值,而不是在 Calendar 对象上设置这些值。因此,在线程 2 中创建一个 Calendar 对象,设置用户定义的值,并在每一秒睡眠后递增时间。

    Thread t2 = new Thread(){
        public void run(){
            clockSet = true;
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(tfhour.getText()));
            cal.set(Calendar.MINUTE, Integer.parseInt(tfminute.getText()));
            cal.set(Calendar.SECOND, Integer.parseInt(tfsecond.getText()));
            while(true){                    
                    int hour = cal.get(Calendar.HOUR_OF_DAY);
                    int minute = cal.get(Calendar.MINUTE);
                    int second = cal.get(Calendar.SECOND);                   
                   lblKlockan.setText(hour + ":" + minute + ":" + second);
                   try {
                sleep(1000);
                cal.add(Calendar.SECOND, 1);
            } catch (InterruptedException e) {
                e.printStackTrace();}
          }
         }
       };
    

    玩得开心..!

    【讨论】:

    • 哦,谢谢!如果您只是在这种情况下添加 ActionListiner public void actionPerformed(ActionEvent e) { if(e.getSource() == btnSetTime) { clockSet = true; ,它不应该吗?
    • 这样也行,最重要的是,在启动线程 2 之前,应该有一个变量来控制线程 1 的生命周期。
    • 只是为了确保您理解,java中的线程只能基于条件停止。所以run方法有这个'while'循环来检查标志并决定是否继续。看,我在线程 1 实现中有逻辑来检查这个标志。每当用户单击按钮时,该标志都需要设置为 true。就这些。另外,请注意线程 2 实现在循环中使用相同的 Calendar 对象。
    • okey 所以我按照你说的做了,但是遇到了一些麻烦。所以每当我现在按下按钮时,它都会给我一个冻结的数字,然后就结束了。可能是什么问题?
    • 这就是你使用布尔值的原因,所以如果它为假,它应该给我们当前时间,当点击按钮时,它应该将布尔值更改为真,它应该但不应该:(给我们我输入的值,而不是它只是冻结,这有点奇怪?
    【解决方案2】:

    好的,你看到代码了

    try {
                            for(;;) {
                                int hour = Integer.parseInt(tfhour.getText());//this one
                                int minute = Integer.parseInt(tfminute.getText());//and this one
                                int second = Integer.parseInt(tfsecond.getText());//and this too
    
                                lblKlockan.setText(hour + ":" + minute + ":" + second);
                                sleep(1000);
                            }
    

    您每次都在 for 循环中设置小时、分钟和秒。所以时钟正在重置。

    让它们只被初始化一次,即将它们从循环中取出。


    进一步的代码

    for(;;) {
                                Calendar cal = Calendar.getInstance();
                                int hour = cal.get(Calendar.HOUR_OF_DAY);
                                int minute = cal.get(Calendar.MINUTE);
                                int second = cal.get(Calendar.SECOND);
    
                                lblKlockan.setText(hour + ":" + minute + ":" + second);
                                sleep(1000);
                            }
    

    正在使您的计时器作为时钟而不是计时器工作,因为 1 秒后。小时、分钟和秒根据您从日历获取的时间设置为值。

    因此,您的代码将用作显示当前时间的时钟。

    【讨论】:

    • 嗯,我只删除了 for 循环,结果相同,因为另一个线程也在使用 for(;;)。但没有它,时钟就不会计数。那么可能有什么问题呢?
    • 就像我必须让线程 2 以某种方式接管线程 1,或者在按下按钮时停止线程 1 并使线程 2 工作?
    • 是的,没错。所以线程 1 像时钟一样运行,同时线程 2 仅具有我放入 TextField 中的值,我必须以某种方式使其计数(这就是我不知道的问题)并使其接管来自线程 1,所以它在我的 GUI 中显示了新的时钟。如果你明白我的意思:)? @shivam7357
    • 告诉我你希望你的代码具体做什么:时钟还是计时器?
    • 一个时钟。所以首先它从一个时钟开始,如果我在我的 GUI 等中输入值 12:12:12。它应该将时钟更新为 12:12:12(使用线程 2),然后像时钟一样工作。这将是 12:12:13...12:12:14..... 等等
    【解决方案3】:

    在我看来,您根本不需要第二个线程。在这种情况下,我要做的是创建三个 Int 字段,小时、分钟和秒偏移量,您可以在按下按钮时将其更改为 hourOffset = Calendar.HOUR_OF_DAY - Integer.parseInt(tfhour.getText())%24;(例如小时)。比您只需要将偏移量添加到 thread1 中的时间,因为您从 0 作为偏移量开始,这始终有效。

    【讨论】: