繁体   English   中英

Swing应用程序多线程设计模式和最佳实践

[英]Swing application multithread design patterns and best practices

我一直在阅读很多关于SO的答案和问题,但我从未问过任何问题。

我的问题是有关Swing应用程序中的设计模式和最佳实践。

假设您有一个带有JLabel和另一个类(不是以前的内部类)的GUI类的Swing应用程序,该类扩展了Thread并执行了一些网络操作(基本上是定期从Web API提取资源以检查是否出现给定值) )。

当第二个类获取某个值时,我需要更新firt类的JLabel。 我完全意识到这应该在EDT中使用invokeLater() ,我的问题是如何处理从后台线程到JLabel.setText()方法的访问。

据我所知,我看到了三种解决方案:

  • 在GUI类中提供一个静态getter,并在Thread类中将其现场调用SwingUtilities.invokeLater()
  • 在GUI类内部提供一个静态方法,该方法内部调用SwingUtilities.invokeLater()并从Thread类访问该方法(例如MyGui.updateTheLabel())
  • 将JLabel的引用传递给Thread构造函数,并使用该引用通过SwingUtilities.invokeLater()更新标签

此解决方案哪一个更好? 是否有解决该问题的特定设计模式。 我发现将SwingUtilities.invokeLater()放在我想更新GUI或在周围创建静态吸气剂的地方很丑。

谢谢 :)

要在后台执行任务并在Swing应用程序中更新UI元素,可以使用SwingWorker类。

网络线程不应该了解JLabel。 它的职责是从网络加载一些数据。 在屏幕上显示该数据是另一项任务,应使用特殊的UI类进行。 该类应具有某种方法,例如( update(byte[]) ,该方法内部调用invokeLater 。该UI类的实例应在创建时传递给网络线程,并且该线程应定期调用update方法。

我通常为将在GUI上执行的任务定义可运行对象,并在需要时创建它们。 局外人不需要知道更新的执行方式,他们只是使用GUI的公开API。

例:

interface NetworkUpdateListener {
    void updateFetched(String newText);
}

class Gui implements NetworkUpdateListener {
    private JLabel label;
        // ...

    @Override
    public void updateFetched(String newText) {
        SwingUtilities.invokeLater(new LabelUpdater(newText));
    }

    private final class LabelUpdater implements Runnable {
        private final String text;

        LabelUpdater(String s) { text = s; }

        @Override
        public void run() { label.setText(text); }
    }
}

在其他地方,从另一个线程:

NetworkUpdateListener listener;
// ...
listener.updateFetched(text);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM