如何使用事件分派线程



我了解到swing不是线程安全的。深入研究后,我发现对swing组件的每次修改都必须在事件调度线程上完成,以防止与多线程相关的各种问题。然而,信息似乎完全停止了。似乎没有一个好的教程来解释如何在互联网上可以访问的任何地方做到这一点。

从与其他问题相关的代码中拼凑信息,似乎我必须在我的程序中的每一个swing修改周围放置一个不整洁的代码块(就像我自己的代码中的这个例子):

try {
        SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                setTitle("Frame title");
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                setVisible(true);
                setSize(800, 480);
                setLocationRelativeTo(null);
                setIconImage(Toolkit.getDefaultToolkit().createImage(ClassLoader.getSystemResource("Frame icon.png")));
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
基本上,这是对的吗?我是否必须将该代码(或与invokeLater等效的代码)放在对代码中Swing组件的每次修改周围?

还有,为什么Swing不自动做这个?

诀窍是,当swing调用您时,它将始终在EDT中,因此您不必担心它。

然而,如果你是在一个定时器或一个动作触发一些其他外部事件,你的主线程或任何其他线程你已经创建了,那么是的,你必须使用invokeLater或invokeAndWait。

换句话说,yes swing确实会自动完成"它"。很少需要使用invokeXx,如果swing在内部使用它会浪费太多时间。

许多java程序员从来没有弄清楚这一点,这可能会在绘制GUI时导致一些非常讨厌的难以发现的问题。我真希望swing在你不使用EDT调用它时抛出一个异常——如果它这样做,Java在专业gui方面会有更好的声誉,因为那里会少一些垃圾。

注意,从事件处理程序执行的任何代码都已经在EDT(缩写中的event)中运行了

这意味着对于一般使用(当你不乱用swingworker和线程池之类的),你总是在EDT

里面。

,您可以随时查询是否与SwingUtilities.isEventDispatchThread()在EDT中

还要注意,在代码中,当您已经在EDT

中时,对invokeAndWait的调用将失败并抛出错误。

基本上,您不能从EDT外部绘制或更新GUI。您可以在另一个线程中使用SwingUtilitis.invokeLater()来确保GUI绘图或更新代码在EDT上运行。

并非所有UI代码都必须是invokeLater调用中可运行代码的一部分。这仅仅是因为程序的很大一部分将在EDT上运行。只有当您在不同的线程上时,才需要将消息分派给EDT。

最新更新