小编典典

我应该在EDT中分配/创建秋千元素吗?

java

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

我在编辑非线程安全的图形元素时遇到了并发性问题,但我正在创建它们,但尚未显示出来,如果它们太多或需要花费一些时间来分配,这将冻结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()


阅读 210

收藏
2020-11-30

共1个答案

小编典典

在Swing
可分离模型体系结构中
,视图组件侦听其模型。因为视图可以任意响应模型更新生成的事件,所以相应的模型 必须在EDT上进行更新。您可以通过以下两种基本方法之一来减少延迟:

由于大小,您一定要在后台加载文件,以避免阻塞事件分发线程;SwingWorker是一个常见的选择。与其使用a Document,不如考虑更新aTableModel并在a的行中显示文本行JTable。这具有几个优点:

  • 结果将立即开始显示,并且可以减少感知到的延迟。

  • JTable使用flyweight模式进行渲染,该模式可以很好地扩展到数兆字节,百万行的范围。

  • 您可以在读取输入时对其进行解析,以创建任意列结构。

  • 您可以利用排序和过滤的功能JTable,为例子。

  • 您可以用来TablePopupEditor将重点放在一行上。

附录:以下示例DefaultTableModel为方便起见。为了降低开销,扩展AbstractTableModel和管理List或List,如图所示这里。该示例显示不确定的进度;显示中间进度的更改在此处显示。

码:

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

/**
 * @see https://stackoverflow.com/a/25526869/230513
 */
public class DisplayLog {

    private static final String NAME = "/var/log/install.log";

    private static class LogWorker extends SwingWorker<TableModel, String> {

        private final File file;
        private final DefaultTableModel model;

        private LogWorker(File file, DefaultTableModel model) {
            this.file = file;
            this.model = model;
            model.setColumnIdentifiers(new Object[]{file.getAbsolutePath()});
        }

        @Override
        protected TableModel doInBackground() throws Exception {
            BufferedReader br = new BufferedReader(new FileReader(file));
            String s;
            while ((s = br.readLine()) != null) {
                publish(s);
            }
            return model;
        }

        @Override
        protected void process(List<String> chunks) {
            for (String s : chunks) {
                model.addRow(new Object[]{s});
            }
        }
    }

    private void display() {
        JFrame f = new JFrame("DisplayLog");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        DefaultTableModel model = new DefaultTableModel();
        JTable table = new JTable(model);
        JProgressBar jpb = new JProgressBar();
        f.add(jpb, BorderLayout.NORTH);
        f.add(new JScrollPane(table));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        LogWorker lw = new LogWorker(new File(NAME), model);
        lw.addPropertyChangeListener((PropertyChangeEvent e) -> {
            SwingWorker.StateValue s = (SwingWorker.StateValue) e.getNewValue();
            jpb.setIndeterminate(s.equals(SwingWorker.StateValue.STARTED));
        });
        lw.execute();
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new DisplayLog().display();
        });
    }
}
2020-11-30