我应该 allocate/create 将元素转换为 EDT 吗?

Should I allocate/create swing elements into EDT?

我应该在 EDT 中创建 swing 元素吗?

我遇到了编辑非线程安全图形元素的并发问题,但我正在创建它们,它们还没有显示,如果它们很多或者它们需要一些时间来分配就会冻结GUI,不是吗?

这里是我使用 EDT 显示但不创建我的 GUI 结构的示例:

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();
        }

    }
}

还没有显示元素,可以吗?还是我应该全部移动到 initUI()?

Swing Threading Policy 状态:

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.

在 Swing separable model architecture 中,视图组件监听其模型。由于视图可能会任意响应模型更新生成的事件,因此相应的模型必须 在 EDT 上更新。您可以通过以下两种基本方法之一来减少延迟: