计时器阻止Swing中的线程

时间:2018-12-09 06:49:27

标签: java swing timer

我正在尝试使用Java创建计时器应用程序,但是在计数过程中,直到计数器完成,它才会执行main(也将打开窗口)。 这就是我的意思:

long timeElapsed = 0;
    long timeStart = System.currentTimeMillis();
    for (long counter=0;counter<5;++counter) {
        TimeUnit.SECONDS.sleep(1);
        timeElapsed = (System.currentTimeMillis() - timeStart)/1000;
        display.setText(Long.toString(timeElapsed));
    }
    String myString = Long.toString(timeElapsed);

程序在for语句完成之前不会创建窗口,这很糟糕,因为它不会显示直到完成的时间,这并不是我想要的。 运行窗口时是否有任何方法可以使窗口显示经过的时间?

我的代码:

import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.util.concurrent.TimeUnit;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JButton;

public class TimerGUI {

    private JFrame frame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    TimerGUI window = new TimerGUI();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     * @throws InterruptedException 
     */
    public TimerGUI() throws InterruptedException {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     * @throws InterruptedException 
     */
    private void initialize() throws InterruptedException {
        JLabel display = new JLabel("a");
        // TIME
        long timeElapsed = 0;
        long timeStart = System.currentTimeMillis();
        for (long counter=0;counter<5;++counter) {
            TimeUnit.SECONDS.sleep(1);
            timeElapsed = (System.currentTimeMillis() - timeStart)/1000;
            display.setText(Long.toString(timeElapsed));
        }
        String myString = Long.toString(timeElapsed);


        //WINDOW
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);

        // LABEL
        //display = new JLabel(myString);
        display.setBounds(165, 64, 89, 54);
        frame.getContentPane().add(display);


        //BUTTON
        JButton btnNewButton = new JButton("New button");
        btnNewButton.setBounds(165, 169, 89, 32);
        frame.getContentPane().add(btnNewButton);



    }
}

注意:我尚未使用程序的Button部分,并且我试图修复的代码也位于方法Initialize()中。

2 个答案:

答案 0 :(得分:1)

欢迎来到“亲爱的,我阻止了事件调度线程”的美好世界

Swing既是单线程也不是线程安全的。这意味着,如果通过执行Thread.sleep之类的操作来阻止事件分发线程,则UI将无法更新,因为您已阻止了负责更新它的线程。

同样,您不应从EDT上下文之外更新UI或UI依赖的任何内容,而这将使您陷入困境。

对我们来说很幸运,Swing开发人员预见到了这一问题,并提供了许多可能的解决方案,就您而言,最好的是可能是旧的Swing Timer

首先查看Concurrency in SwingHow to use Swing Timers以获得更多详细信息。

我还应该添加Timer(和Thread.sleep)本质上不准确的内容,仅保证“至少”的准确性。不要使用计数器来跟踪它们已经运行了多长时间,而应该使用java.time API for example

答案 1 :(得分:0)

您可以在下面引用以下链接:

在该方法中,您可以使用经过的时间来更新UI组件(例如JLabel)

Java Swing Timer