1

Should I create swing elements into EDT?

I got the concurrency problems with editing non thread-safe graphics elements, but I'm creating them, they aren't shown yet, and if they are a lot or they take some time to be allocated that would freeze the GUI, doesn't it?

Here an example where I use EDT to display but not to create my GUI structure:

public class Launcher {
    private final SwingWorker worker;
    private final JFrame frame;
    private final JLabel label;
    private final JProgressBar progressBar;

    public Launcher() {

        // init user interface
        frame = new JFrame();
        JPanel panel = new JPanel(new BorderLayout());
        label = new JLabel("Launching...", SwingConstants.CENTER);
        progressBar = new JProgressBar(0, 100);
        progressBar.setIndeterminate(true);
        panel.add(label, BorderLayout.CENTER);
        panel.add(progressBar, BorderLayout.PAGE_END);
        initUI(panel);
        worker = new LauncherWorker(this);
        worker.addPropertyChangeListener((PropertyChangeListener)this);
    }

    private void initUI(final Component panel) {
        if (!SwingUtilities.isEventDispatchThread()) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    DirectaChatLauncher.this.initUI(panel);
                } //run()
            });
            return;
        }
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(panel, BorderLayout.PAGE_END);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if ("progress".equals(evt.getPropertyName())) {
            int progress = (Integer) evt.getNewValue();
            progressBar.setValue(progress);
        }
    }

    private void setProgression(final String msg) {
        label.setText(msg);
    }

    class LauncherWorker extends SwingWorker<Boolean, String> {

        private final Launcher LAUNCHER;

        public LauncherWorker(Launcher launcher) {
            super();
            LAUNCHER = launcher;
        }

        @Override
        protected Boolean doInBackground() throws Exception {
            setProgress(0);
            publish("Started");
            ...
            setProgress(100);
            publish("Launched");
            Thread.sleep(1000);
            return Boolean.TRUE;
        }

        @Override
        protected void process(List<String> chunks) {
            LAUNCHER.setProgression(chunks.get(0));
        }

        @Override
        public void done() {
            LAUNCHER.done();
        }

    }
}

is it fine since the elements weren't displayed yet? or should I move all into initUI()?

Lii
  • 11,553
  • 8
  • 64
  • 88
Luca Ricci
  • 95
  • 9
  • 1
    I'm not sure about your problem, it is a bit vague or badly formulated. Do you have any code that we can look at that makes your issue clearer? – mattiash Nov 04 '15 at 11:28
  • @mattiash I added some example code, but I was asking why I should create swing item in EDT and not simply modify their status using it? – Luca Ricci Nov 04 '15 at 12:43
  • Since you have already beein notified of the thread policy, let me just refer you to this previous question on stack overflow. http://stackoverflow.com/questions/491323/is-it-safe-to-construct-swing-awt-widgets-not-on-the-event-dispatch-thread – mattiash Nov 04 '15 at 14:47
  • As a general rule of thumb, yes. You have no idea when a component might try and generate events, which then need to be processed within the context of the EDT – MadProgrammer Nov 04 '15 at 22:27

2 Answers2

3

In the Swing separable model architecture, a view component listens to its model. Because a view may respond arbitrarily to events generated by model updates, the corresponding model must also be updated on the EDT. You can mitigate latency via one of two basic approaches:

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
2

Swing Threading Policy states:

In general Swing is not thread safe. All Swing components and related classes, unless otherwise documented, must be accessed on the event dispatching thread. Typical Swing applications do processing in response to an event generated from a user gesture. For example, clicking on a JButton notifies all ActionListeners added to the JButton. As all events generated from a user gesture are dispatched on the event dispatching thread, most developers are not impacted by the restriction.

Where the impact lies, however, is in constructing and showing a Swing application. Calls to an application's main method, or methods in Applet, are not invoked on the event dispatching thread. As such, care must be taken to transfer control to the event dispatching thread when constructing and showing an application or applet. The preferred way to transfer control and begin working with Swing is to use invokeLater. The invokeLater method schedules a Runnable to be processed on the event dispatching thread.

WalterM
  • 2,686
  • 1
  • 19
  • 26
  • I got that you must avoid access to components outside the EDT but I'm creating them, they still can't generate event or anything. Then, to show them, I'm using EDT – Luca Ricci Nov 04 '15 at 12:53
  • 1
    @LucaRicci: Updating a component's model generates a view event; more [here](http://stackoverflow.com/a/33523421/230513). – trashgod Nov 04 '15 at 13:43