简体   繁体   中英

Swing application multithread design patterns and best practices

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:

  • provide a static getter in the GUI class and call it insite a SwingUtilities.invokeLater() in the Thread class
  • provide a static method inside the GUI class which internally calls SwingUtilities.invokeLater() and access that method (say MyGui.updateTheLabel()) from the Thread class
  • passing a reference of the JLabel to the Thread constructor and use that reference to update the label with SwingUtilities.invokeLater()

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.

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