I've been reading a lot of SO answer and questions but I never asked anything before.
My question is about desing patterns and best practices in Swing application.
Suppose you have a Swing application with a GUI class with a JLabel and another class (not an inner class of the previous) which extends Thread and perform some network operations (basically it periodically fetch resources from a web API to check if a given value appear).
When a certain value is fetched by the second class I need to update the JLabel of the firt class. I'm perfectly aware this should be done in the EDT using invokeLater()
, my question is how to handle the access from the background Thread to the JLabel.setText() method.
As far as I know I see three solution:
SwingUtilities.invokeLater()
in the Thread class SwingUtilities.invokeLater()
and access that method (say MyGui.updateTheLabel()) from the Thread class Which one of this solution is better? Are there particular design patterns meant to solve this issue. I find it ugly to put SwingUtilities.invokeLater() everywhere I want to update the GUI or creating static getters around.
Thank you :)
要在后台执行任务并在Swing应用程序中更新UI元素,可以使用SwingWorker类。
The networking thread should not know about JLabel. Its duty is to load some data from network. Exposing that data on a screen is another task, and should be made with a special UI class. That class should have some method like ( update(byte[])
, which internally calls invokeLater
. An instance of that UI class should be passed to the networking thread at creation time, and that thread should periodically call update
method.
I usually define runnables for the tasks I'll be performing on the GUI, and create these when needed. Outsiders need not know how the updates are performed, they just use the GUI's exposed API.
Example:
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); }
}
}
Somewhere else, from another thread:
NetworkUpdateListener listener;
// ...
listener.updateFetched(text);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.