当前位置: 首页 > 知识库问答 >
问题:

巨大数据负载下对JTable行选择事件的延迟响应

仲元凯
2023-03-14

我有一个SwingJTable动态更新了大量数据,新的行不断地被实时添加,大约1000-2000行可以在几分钟内添加。我已经注册了一个监听器来响应使用的单行选择事件来执行一些操作。我使用了Observer模式进行Swing数据绑定,表的模型由WritableList实现支持。因此,新项目从表自身的领域添加到表中。监听器是从SWT UI线程添加的。问题是,当向表中添加新行时,它不会立即响应用户行选择事件。只有在停止更新表格模型时,表格才会根据用户选择做出响应——有时延迟超过30-60秒。请帮助我理解为什么我的表格模型在密集更新时不会立即响应用户选择,以及如何克服这个限制。如有任何建议,将不胜感激。

共有1个答案

利俊迈
2023-03-14

使用SwingWorkerpublish()后台的行,并在process()的实现中更新TableModelSwingWorker将限制更新到可持续的速度。配置文件以确保您没有阻止事件分派线程。

附录:经过测试,GUI对这1000000行的变化保持响应。分析时,请注意,每次单击“Go”按钮都会启动一个新的工作进程。

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;

/** @see https://stackoverflow.com/a/17415635/230513 */
public class TestTableLoad01 {

    public static void main(String[] args) {
        new TestTableLoad01();
    }

    public TestTableLoad01() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                final MyTableModel model = new MyTableModel();
                JTable table = new JTable(model);
                table.setDefaultRenderer(Date.class, new TimeCellRenderer());

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                frame.add(new JButton(new AbstractAction("Go") {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        TableSwingWorker worker = new TableSwingWorker(model);
                        worker.execute();
                    }
                }), BorderLayout.SOUTH);
            }
        });
    }

    public class TimeCellRenderer extends DefaultTableCellRenderer {

        private DateFormat df;

        public TimeCellRenderer() {
            df = new SimpleDateFormat("HH:mm:ss");
        }

        @Override
        public Component getTableCellRendererComponent(JTable table,
            Object value, boolean isSelected, boolean hasFocus, int row, int column) {

            if (value instanceof Date) {

                value = df.format(value);

            }

            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

            return this;

        }
    }

    public class MyTableModel extends AbstractTableModel {

        private String[] columnNames = new String[]{"Date", "Row"};
        private List<RowData> data;

        public MyTableModel() {
            data = new ArrayList<RowData>(25);
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return columnIndex == 0 ? Date.class : Integer.class;
        }

        @Override
        public String getColumnName(int col) {
            return columnNames[col];
        }

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        @Override
        public int getRowCount() {
            return data.size();
        }

        @Override
        public Object getValueAt(int row, int col) {
            RowData value = data.get(row);
            return col == 0 ? value.getDate() : value.getRow();
        }

        public void addRow(RowData value) {
            int rowCount = getRowCount();
            data.add(value);
            fireTableRowsInserted(rowCount, rowCount);
        }

        public void addRows(RowData... value) {
            addRows(Arrays.asList(value));
        }

        private void addRows(List<RowData> rows) {
            int rowCount = getRowCount();
            data.addAll(rows);
            fireTableRowsInserted(rowCount, getRowCount() - 1);
        }
    }

    public class RowData {

        private Date date;
        private int row;

        public RowData(int row) {
            this.date = new Date();
            this.row = row;
        }

        public Date getDate() {
            return date;
        }

        public int getRow() {
            return row;
        }
    }

    public class TableSwingWorker extends SwingWorker<MyTableModel, RowData> {

        private final MyTableModel tableModel;

        public TableSwingWorker(MyTableModel tableModel) {
            this.tableModel = tableModel;
        }

        @Override
        protected MyTableModel doInBackground() throws Exception {

            // This is a deliberate pause to allow the UI time to render
            Thread.sleep(1000);

            System.out.println("Start polulating");

            for (int index = 0; index < 1000000; index++) {

                RowData data = new RowData(index);
                publish(data);
                Thread.yield();
            }
            return tableModel;
        }

        @Override
        protected void process(List<RowData> chunks) {
            System.out.println("Adding " + chunks.size() + " rows");
            tableModel.addRows(chunks);
        }
    }
}

 类似资料:
  • 问题内容: 我有秋千 动态更新大量数据- 不断地实时添加新行,并且可以在几分钟内添加大约1000-2000行。我已经注册了一个侦听器来响应使用单行选择事件来执行一些工作。我已将Observer模式用于Swing数据绑定,并且表的模型由WritableList实现支持。因此,新项目将从其自己的领域添加到表中。侦听器是从SWT UI线程添加的。问题是,将新行添加到表时,它不会在用户行选择事件时立即响应

  • 问题内容: 我正在测试Django + Celery,您好是世界示例。使用RabbitMQcelery可以正常工作,但是当我切换到Redis经纪人/结果时,我得到以下信息: settings.py task.py 上面的测试中有什么问题吗? 问题答案: 我发现解决方案是源代码:http : //docs.celeryproject.org/en/latest/_modules/celery/res

  • 问题内容: 我需要在循环中对数据库进行SQL查询: 更好的方法是:保持原样或循环后移动: 或者是其他东西 ? 问题答案: 整个要点是直到函数返回才执行,因此将其放置在要关闭的资源打开后的适当位置。但是,由于要在循环内创建资源,因此根本不要使用defer- 否则,在函数退出之前,您不会关闭在循环内创建的任何资源,因此它们会堆积直到然后。相反,您应该在每次循环迭代结束时关闭它们, 而无需 :

  • 本文向大家介绍对vue事件的延迟执行实例讲解,包括了对vue事件的延迟执行实例讲解的使用技巧和注意事项,需要的朋友参考一下 vue事件的延迟执行: 以上这篇对vue事件的延迟执行实例讲解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。

  • 我的地图中存储了3个对象——每个都有几个MB。它们不会改变,所以在节点本地缓存它们是有意义的。这就是我在意识到平均获取延迟很大之前所做的,这大大减慢了我的计算速度。请看hazelcast控制台: 这让我想知道它是从哪里来的。我认为最初发生的是90和48次失误吗?这些计算是并行运行的,所以我认为它们都可以在条目被缓存之前发出一个reguest来获取,因此所有这些都不会从近缓存中受益。那么它是某种预加

  • 问题内容: 我目前正在使用JTable来显示数据库中的内容。我想为用户提供便利,以便他可以使用Shift +箭头键选择想要的行数,然后稍后使用提供的删除选项删除那些记录。请提供一个小例子。 问题答案: 您需要允许多项选择: 然后,您需要编写适当的选择侦听器。这有点困难,请尝试在Google相关解决方案中查找。您可以看一个选择侦听器的示例。