2

我在我的 java 应用程序中遇到了一个问题,当通过单击 jButton 打开新的 jFrames 时,会出现一点点冻结并在其打开后(冻结时间 1-2 分钟/3 分钟)。我还找不到发生了什么问题。但我对以下附加代码有一些疑问。该代码用于获取系统时间和日期并显示所有 jFrames。所以这段代码在所有的jFrames中。现在我的问题是,这段代码是否发生了这种冻结..?或者可能有任何其他原因..?如果这段代码有任何错误,请告诉我……我正在使用 NETbeans 8.2。提前致谢。

代码:

public AdminHome() {
    initComponents();

    new Thread(new Runnable() {
        @Override
        public void run() {

            while (true) {
            Date d=new Date();

            SimpleDateFormat sd=new SimpleDateFormat("yyyy - MM - dd");
            String s =  sd.format(d);
            String s1 = d.toString();
            String ar[]=s1.split(" ");

            jLbl_Date.setText(s);  
            jLbl_Time.setText(ar[3]);
            }  
        }
    }).start();

}
4

3 回答 3

2

这两个调用:

jLbl_Date.setText(s);  
jLbl_Time.setText(ar[3]);

必须在 EDT(事件调度线程)上发生,因为必须从 EDT 操作 GUI 组件。您可以使用以下方法将它们包装在 EDT 上SwingUtilities

SwingUtilities.invokeLater(() -> {
    Date d=new Date();

    SimpleDateFormat sd=new SimpleDateFormat("yyyy - MM - dd");
    String s =  sd.format(d);
    String s1 = d.toString();
    String ar[]=s1.split(" ");

    jLbl_Date.setText(s);  
    jLbl_Time.setText(ar[3]);
});

但是,仍然会有问题。由于您的线程在更新标签之间不会休眠,因此您将使用更新请求淹没 EDT,从而导致您的 GUI 再次冻结。Thread.sleep(1000);您可以通过在更新标签后添加 a 来解决此问题。

一种更优雅的方法是使用摆动计时器而不是您的线程:

Timer timer = new Timer(1000, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            Date d=new Date();

            SimpleDateFormat sd=new SimpleDateFormat("yyyy - MM - dd");
            String s =  sd.format(d);
            String s1 = d.toString();
            String ar[]=s1.split(" ");

            jLbl_Date.setText(s);  
            jLbl_Time.setText(ar[3]);
        }
});            
timer.setInitialDelay(0);
timer.start();

摆动计时器负责确保在actionPerformedEDT 上执行带有 -method 的代码。它还有一个额外的优势,它可以在需要时合并事件 - 另一个机制来防止事件淹没 EDT。

于 2017-02-22T15:14:44.727 回答
0

看起来您已经创建了一个线程来运行无限循环来更新某些日期和时间字段。这不是实现您想要做的事情的好方法。

更好的解决方案是使用javax.swing.Timer间隔较短的 a 并从附加的操作侦听器更新您的 UI。

ActionListener timerListener = new ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        Date d=new Date();

        SimpleDateFormat sd=new SimpleDateFormat("yyyy - MM - dd");
        String s =  sd.format(d);
        String s1 = d.toString();
        String ar[]=s1.split(" ");

        jLbl_Date.setText(s);  
        jLbl_Time.setText(ar[3]);
    }
};

Timer t = new javax.swing.timer(1000, timerListener).start();

像上面这样的东西应该可以解决问题。这为您节省了跨越线程边界来更新 UI 的麻烦,并且与您之前的解决方案相比,将大大减少 CPU 负载。

于 2017-02-22T15:18:47.597 回答
0

您可能已经创建了一个单独的线程,但所有 UI 更新都源于 AWT 线程。因此,该线程非常频繁地调用jLbl_date.setText()和方法实际上直接阻塞了 AWT 线程。jLbl_time.setText()

尝试添加一个sleep(1000)after jLbl_Time.setText()

于 2017-02-22T14:59:31.997 回答