我一直在阅读很多回答和问题,但我以前从未问过任何问题。
我的问题是关于Swing应用程序中的模式和最佳实践。
假设你有一个带有JLabel的GUI类的Swing应用程序和另一个类(不是前面的内部类),它扩展了Thread并执行了一些网络操作(基本上它定期从Web API获取资源以检查是否存在给定值出现)。
当第二个类获取某个值时,我需要更新firt类的JLabel。我完全知道这应该在EDT中使用invokeLater()
来完成,我的问题是如何处理从后台线程到JLabel.setText()方法的访问。
据我所知,我看到了三个解决方案:
SwingUtilities.invokeLater()
SwingUtilities.invokeLater()
并从Thread类访问该方法(比如MyGui.updateTheLabel())哪种解决方案更好?是否有特定的设计模式可以解决这个问题。我觉得将SwingUtilities.invokeLater()放到我想要更新GUI或创建静态getter的地方是很难看的。
谢谢:)
答案 0 :(得分:2)
要在后台执行任务并在Swing应用程序中更新UI元素,您可以使用SwingWorker类。
答案 1 :(得分:2)
网络线程不应该知道JLabel。它的职责是从网络加载一些数据。在屏幕上公开这些数据是另一项任务,应该使用特殊的UI类。该类应该有一些方法,如(update(byte[])
,内部调用invokeLater
。该UI类的一个实例应该在创建时传递给网络线程,该线程应定期调用{{1}方法。
答案 2 :(得分:0)
我通常为我将在GUI上执行的任务定义runnables,并在需要时创建它们。局外人不需要知道如何执行更新,他们只是使用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);