【问题标题】:How do I make a thread wait for JFrame to close in Java?如何让线程等待 JFrame 在 Java 中关闭?
【发布时间】:2010-11-23 10:11:13
【问题描述】:

程序启动时,会创建一个新的 JFrame。一旦用户单击开始按钮,就会创建并启动一个线程。该线程执行的一部分是验证表单上的数据,然后使用该数据执行。验证数据后,线程在原始帧上调用 dispose(),然后创建一个充当控制面板的新 JFrame。

程序还有一个完全不显示任何GUI的自动模式,该模式从配置文件中读取数据,然后启动执行线程并运行所有内容,但没有控制面板。

我希望程序在线程完成后结束,但在 GUI 模式下,前提是用户也关闭了控制面板。 是否可以让线程等待框架关闭。我假设框架是从它自己的线程运行的?还是不是这样。

谢谢。

【问题讨论】:

    标签: java multithreading user-interface


    【解决方案1】:

    你选择的答案有点尴尬。使用 Thread.sleep(1000) 将每秒检查一次窗口状态。这不是性能问题,而只是糟糕的编码风格。您可能只有一秒的响应时间。

    这段代码稍微好一点。

    private static Object lock = new Object();
    private static JFrame frame = new JFrame();
    /**
     * @param args
     */
    public static void main(String[] args) {
    
        frame.setSize(300, 300);
        frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        frame.setVisible(true);
    
        Thread t = new Thread() {
            public void run() {
                synchronized(lock) {
                    while (frame.isVisible())
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    System.out.println("Working now");
                }
            }
        };
        t.start();
    
        frame.addWindowListener(new WindowAdapter() {
    
            @Override
            public void windowClosing(WindowEvent arg0) {
                synchronized (lock) {
                    frame.setVisible(false);
                    lock.notify();
                }
            }
    
        });
    
        t.join();
    }
    

    【讨论】:

    • 是的,我明白为什么这样会更好。谢谢。
    • 我认为最后缺少一个 t.join()
    【解决方案2】:

    您可以从您的线程中引用 JFrame。然后将JFrame的默认关闭操作设置为HIDE_ON_CLOSE。如果 JFrame 已关闭,则可以停止线程。

    示例代码:

    import java.awt.Dimension;
    
    import javax.swing.JFrame;
    
    public class FrameExample extends JFrame {
    
        public FrameExample() {
            setSize(new Dimension(100, 100));
            setDefaultCloseOperation(HIDE_ON_CLOSE);
            setVisible(true);
    
        }
    
        private static class T implements Runnable {
    
            private FrameExample e;
    
        public T(FrameExample e) {
            this.e = e;
        }
    
        @Override
        public void run() {
            while (true) {
                if (e.isVisible()) {
                    // do the validation
                    System.out.println("validation");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                        break;
                    }
                }
            }
        }
    
    }
    
    public static void main(String[] args) {
        FrameExample frameExample = new FrameExample();
    
        new Thread(new T(frameExample)).start();
        }
    } 
    

    【讨论】:

    • 谢谢,这正是我所需要的。
    • 这具有比其他答案更不紧密的优势。框架和线程都必须在另一个答案中相互了解这一事实对我来说有些问题。此外,睡眠可能会下降很多并且不会影响性能。我经常睡觉(100)几乎完全不引人注意。
    【解决方案3】:

    所有 Swing 组件,包括 JFrame,都由单个线程管理,称为事件调度线程或 EDT。 (可以从其他线程调用 Swing 对象上的方法,但这通常是不安全的,除非在少数情况下与此处无关。)

    您可能会通过将数据验证和执行代码放在它自己的对象中来完成您想要的,否则它完全不知道外部世界。然后,从其他两个对象之一调用它:一个管理 GUI,另一个以“自动模式”运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-22
      • 1970-01-01
      • 2012-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多