如何使用RowHeader处理JTable中的RowSorter同步?

问题描述 投票:4回答:1

以下情况:我有一个带行标题的J(X)表(作为指导我使用了Rob Camicks中的一个很棒的qazxsw poi)。一切都按预期工作。

根据要求,我从服务器收到的数据已经包含一个tablerownumber,我必须在rowheader中显示,数据应该是可过滤的。所以我扩展了示例,并添加了一个过滤器。当我过滤视图时,我看到了行号中的间隙(例如:1,3,6,...),这是所需的效果。

为了能够通过我自己的tablerow过滤和排序表,我添加了一个Examples。在这里,我开始感到困惑。该示例对mainTable和rowHeaderTable使用相同的TableModel和SelectionModel:

TableRowSorter

这很好,因为我不必同步它们。但是关于setModel( main.getModel() ); setSelectionModel( main.getSelectionModel() ); 我突然不确定,如果我也可以甚至不得不使用相同的TableRowSorter-Instance或者我必须为每张桌子创建一个TableRowSorter。首先我把它们添加到两个表中,因为这看起来很实际,但在很多情况下我得到了TableRowSorter。经过一番挖掘后,我发现这是因为IndexOutOfBound-Exceptions在每个TableRowSorter上都会更新两次,因为每个表(RowHeader和MainTable)都会自己通知TableModelEvent有关表更改的信息。

现在我不确定哪条路要走。我想到了以下解决方案:我应该添加第二个TableRowSorter(每个表一个)并同步它们,还是应该将RowMeaderTable中的TableModel包装起来并让它不激活任何事件?或者也许我应该创建我自己的RowHeaderTable类型,它不会通知分拣机有关变化的信息?

java swing jtable tablerowsorter rowheader
1个回答
3
投票

这里是一个快速(注意:没有经过正式测试!使用示例正常工作)包装RowSorter的实现。

  • 在接收模型更改通知时不做任何事情
  • 委派所有状态查询
  • 侦听包装的rowSorter并传播其事件

客户端有责任使其与主表中使用的rowSorter保持同步

用法示例(根据SwingX测试基础结构和SwingX sortController / table):

TableRowSorter

RowSorterWrapper:

public void interactiveRowSorterWrapperSharedXTable() {
    final DefaultTableModel tableModel = new DefaultTableModel(list.getElementCount(), 2) {

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

    };
    for (int i = 0; i < tableModel.getRowCount(); i++) {
        tableModel.setValueAt(i, i, 0);
        tableModel.setValueAt(tableModel.getRowCount() - i, i, 1);
    }
    final JXTable master = new JXTable(tableModel);
    final TableSortController<TableModel> rowSorter = (TableSortController<TableModel>) master.getRowSorter();
    master.removeColumn(master.getColumn(0));
    final JXTable rowHeader = new JXTable(master.getModel());
    rowHeader.setAutoCreateRowSorter(false);
    rowHeader.removeColumn(rowHeader.getColumn(1));
    rowHeader.setRowSorter(new RowSorterWrapper<TableModel>(rowSorter));
    rowHeader.setSelectionModel(master.getSelectionModel());
    // need to disable selection update on one of the table's 
    // otherwise the selection is not kept in model coordinates
    rowHeader.setUpdateSelectionOnSort(false);
    JScrollPane scrollPane = new JScrollPane(master);
    scrollPane.setRowHeaderView(rowHeader);
    JXFrame frame = showInFrame(scrollPane, "xtables (wrapped sortController): shared model/selection");
    Action fireAllChanged = new AbstractAction("fireDataChanged") {

        @Override
        public void actionPerformed(ActionEvent e) {
            tableModel.fireTableDataChanged();
        }

    };
    addAction(frame, fireAllChanged);
    Action removeFirst = new AbstractAction("remove firstM") {

        @Override
        public void actionPerformed(ActionEvent e) {
            tableModel.removeRow(0);

        }
    };
    addAction(frame, removeFirst);
    Action removeLast = new AbstractAction("remove lastM") {

        @Override
        public void actionPerformed(ActionEvent e) {
            tableModel.removeRow(tableModel.getRowCount() - 1);

        }
    };
    addAction(frame, removeLast);
    Action filter = new AbstractAction("toggle filter") {

        @Override
        public void actionPerformed(ActionEvent e) {
            RowFilter filter = rowSorter.getRowFilter();
            if (filter == null) {
                rowSorter.setRowFilter(RowFilter.regexFilter("^1", 1));
            } else {
                rowSorter.setRowFilter(null);
            }

        }
    };
    addAction(frame, filter);
    addStatusMessage(frame, "row header example with RowSorterWrapper");
    show(frame);
}
© www.soinside.com 2019 - 2024. All rights reserved.