【问题标题】:EDT location with several JFrame window带有多个 JFrame 窗口的 EDT 位置
【发布时间】:2011-11-04 13:17:27
【问题描述】:

我有一个 Swing JFrame。如果我在程序执行期间在新线程中创建一个新的 JFrame,那么 EDT 会在哪里?在最后一个 JFrame 窗口的当前线程中或在第一个窗口中。

编辑: 感谢您的回答。

我理解他们,我对他们没意见。我知道我们不必在 EDT 的其他地方创建摇摆对象,但我遇到了问题。

我解释;我开发了一个 JAVA 应用程序来创建和提取像 winrar 这样的存档。您可以使用多线程同时创建多个存档。最近,我想在每次创建时在新的 JFrame 中以 JprogressBar 的形式在归档创建期间添加信息状态。但我的问题是在新状态框架和创建存档的线程中生成通信。这就是为什么,我在存档线程中创建了 JFrame 来更新当前的进度条。

但是就像我可以在潜水员信息源和您的答案/cmets 中阅读它一样,它不利于 java swing 和性能;我无法在 EDT 的其他地方创建摇摆对象。

那么,我该如何解决我的问题呢?

【问题讨论】:

  • 您不应该在 EDT 之外创建任何 Swing 对象,因此您的问题是基于一个无效的前提。 ;-)
  • 似乎其中一个JFrame 实例应该是模态JDialog。当对话框可见时,框架的输入将被阻止。

标签: java swing


【解决方案1】:

EDT - 事件调度线程 - 独立于任何具体的 GUI 组件,例如 JFrame。

通常您应该在 EDT 上创建所有 GUI 组件,但这并不意味着他们拥有 EDT,也不意味着 EDT 拥有这些组件。

要在 EDT 上创建两个 JFrame,您可以执行以下操作:

public static void main(String[] args) {

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            JFrame frame1 = new JFrame("Frame 1");
            frame1.getContentPane().add(new JLabel("Hello in frame 1"));
            frame1.pack();
            frame1.setLocation(100, 100);
            frame1.setVisible(true);
        }
    });

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            JFrame frame2 = new JFrame("Frame 2");
            frame2.getContentPane().add(new JLabel("Hello in frame 2"));
            frame2.pack();
            frame2.setLocation(200, 200);
            frame2.setVisible(true);
        }
    });

}

【讨论】:

    【解决方案2】:

    事件调度线程是固定的。它不会因为你在另一个线程上创建了一个 Swing 对象而被重新分配(无论如何你都不应该这样做)。

    【讨论】:

    【解决方案3】:

    这应该很简单,如果所有事件都在当前EDT中完成,那么EDT不存在,另一个Queue可以声明,

    • 来自 Swing 的听众,
    • 通过将代码封装到invokeLater / invokeAndWait中,
    • 但最安全(对我来说也是最好的)是javax.swing.Action

    输出

    run:
                             Time at : 19:35:21
    There isn't Live EventQueue.isDispatchThread, why any reason for that 
    There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that 
    
                             Time at : 19:35:21
    Calling from EventQueue.isDispatchThread
    Calling from SwingUtilities.isEventDispatchThread
    
                             Time at : 19:35:21
    Calling from EventQueue.isDispatchThread
    Calling from SwingUtilities.isEventDispatchThread
    
                             Time at : 19:35:51
    There isn't Live EventQueue.isDispatchThread, why any reason for that 
    There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that 
    
                             Time at : 19:36:21
    There isn't Live EventQueue.isDispatchThread, why any reason for that 
    There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that 
    
                             Time at : 19:36:51
    There isn't Live EventQueue.isDispatchThread, why any reason for that 
    There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that 
    
                             Time at : 19:37:21
    There isn't Live EventQueue.isDispatchThread, why any reason for that 
    There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that 
    
    BUILD SUCCESSFUL (total time: 2 minutes 17 seconds)
    

    来自代码:

    import java.awt.EventQueue;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.concurrent.*;
    import javax.swing.*;
    
    public class IsThereEDT {
    
        private ScheduledExecutorService scheduler;
        private AccurateScheduledRunnable periodic;
        private ScheduledFuture<?> periodicMonitor;
        private int taskPeriod = 30;
        private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        private Date dateRun;
    
        public IsThereEDT() {
            scheduler = Executors.newSingleThreadScheduledExecutor();
            periodic = new AccurateScheduledRunnable() {
    
                private final int ALLOWED_TARDINESS = 200;
                private int countRun = 0;
                private int countCalled = 0;
    
                @Override
                public void run() {
                    countCalled++;
                    if (this.getExecutionTime() < ALLOWED_TARDINESS) {
                        countRun++;
                        isThereReallyEDT(); // non on EDT
                    }
                }
            };
            periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.SECONDS);
            periodic.setThreadMonitor(periodicMonitor);
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    isThereReallyEDT();
                    JFrame frame1 = new JFrame("Frame 1");
                    frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame1.getContentPane().add(new JLabel("Hello in frame 1"));
                    frame1.pack();
                    frame1.setLocation(100, 100);
                    frame1.setVisible(true);
                }
            });
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    JFrame frame2 = new JFrame("Frame 2");
                    frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame2.getContentPane().add(new JLabel("Hello in frame 2"));
                    frame2.pack();
                    frame2.setLocation(200, 200);
                    frame2.setVisible(true);
                    isThereReallyEDT();
                }
            });
        }
    
        private void isThereReallyEDT() {
            dateRun = new java.util.Date();
            System.out.println("                         Time at : " + sdf.format(dateRun));
            if (EventQueue.isDispatchThread()) {
                System.out.println("Calling from EventQueue.isDispatchThread");
            } else {
                System.out.println("There isn't Live EventQueue.isDispatchThread, why any reason for that ");
            }
            if (SwingUtilities.isEventDispatchThread()) {
                System.out.println("Calling from SwingUtilities.isEventDispatchThread");
            } else {
                System.out.println("There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that ");
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            IsThereEDT isdt = new IsThereEDT();
        }
    }
    
    abstract class AccurateScheduledRunnable implements Runnable {
    
        private ScheduledFuture<?> thisThreadsMonitor;
    
        public void setThreadMonitor(ScheduledFuture<?> monitor) {
            this.thisThreadsMonitor = monitor;
        }
    
        protected long getExecutionTime() {
            long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
            return delay;
        }
    }
    

    【讨论】:

    • +1 即使在add(new JLabel(String.valueOf(1/0))) 之后,EDT 仍然存在!
    • 不明白你的代码是为了展示什么......行为完全符合我的预期:如果从 EDT 调用 isThereReallyEDT(因为它来自于 invokeLater 的可运行),isEventDispatchThread 为真,如果从 EDT 外调用(因为它在调度程序的可运行文件中),则为 true。不是线程专家,但可以肯定 edt 在任何时候都非常活跃,即使事件队列偶尔可能是空的;-)
    • @jfpoilpret 你能评论一下 AWT-EventQueue 到底发生了什么,可以创建第二个
    猜你喜欢
    • 2014-01-07
    • 2011-12-18
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多