jFrames被这段代码冻结了吗? (附代码):Netbeans 8.2

Posted

技术标签:

【中文标题】jFrames被这段代码冻结了吗? (附代码):Netbeans 8.2【英文标题】:jFrames are got freeze by this code? (code attached) : Netbeans 8.2 【发布时间】:2017-07-12 16:31:17 【问题描述】:

我在我的 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();


【问题讨论】:

【参考方案1】:

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

尝试在jLbl_Time.setText() 之后添加sleep(1000)

【讨论】:

另外,setText 调用应该是SwingUtilities.InvokeLatered。 是的,如果我错了,请纠正我,但 AWT 不会像 JavaFX 那样限制多线程 UI 访问。 @Subhranil,tnx 为您解答。我试过你现在说的。但它显示错误。请你可以在这里修改我的代码和评论...?它对我很有用。 JLabel 是 Swing,不应被除事件调度线程之外的任何线程修改。 你好@Colin__s,你说答案我没听懂。请您解释一下修改我的代码...?它对我更有帮助。我只是java的初学者...【参考方案2】:

这两个调用:

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

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

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); 来解决此问题。

更优雅的方法是使用摇摆计时器而不是线程:

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();

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

【讨论】:

你打败了我! +1【参考方案3】:

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

更好的解决方案是使用具有较短间隔的javax.swing.Timer,并从附加的操作侦听器更新您的 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 负载。

【讨论】:

我添加了你的代码。但是出错了,这个jframe也没有运行......它说“没有主要方法”在这里附加了你在我的代码中的代码: 公共 AdminStudent() initComponents(); ActionListener timerListener = new ActionListener public void actionPerformed(ActionEvent e) Date d=new Date(); SimpleDateFormat sd=new SimpleDateFormat("yyyy - MM - dd");字符串 s = sd.format(d);字符串 s1 = d.toString();字符串 ar[]=s1.split(" "); jLbl_Date.setText(s); jLbl_Time.setText(ar[3]); 定时器 t = new javax.swing.timer(1000, timerListener).start(); 我错过了动作监听器末尾的;

以上是关于jFrames被这段代码冻结了吗? (附代码):Netbeans 8.2的主要内容,如果未能解决你的问题,请参考以下文章

Gif 没有在 JFrame 中播放

5年老Android面试竟然被这3道Android基础题难倒了,附大厂真题面经

主线程冻结所有其他线程,包括 java gui 线程

eclipse中jframe如何使用,怎么创建按钮对应的事件,是设置,还是敲代码

如何正确地将字节绘制到JFrame

Android开发UI新技能,你get这个新技能了吗?(附源码详解)