2013-08-02 30 views
4

以下情况:我有一个J(X)表与RowHeader(作为guidline我使用了Rob Camicks伟大的Examples)。所有按预期工作。如何使用RowHeader处理JTable中的RowSorter同步?

enter image description here

通过要求我从服务器接收数据已包含tablerownumber,这是我在的rowHeader显示和数据应该被过滤。所以我扩展了这个例子,并添加了一个过滤器。当我过滤视图时,我在行数中看到了空白(例如:1,3,6,...),这是所需的效果。

为了能够通过我自己的表格对表格进行过滤和排序,我添加了一个TableRowSorter。在这里我开始感到困惑。本例使用相同的TableModel和对selectionModel的和mainTable rowHeaderTable:

setModel(main.getModel()); 
setSelectionModel(main.getSelectionModel()); 

这是伟大的,因为我没有给他们同步。但有关TableRowSorter我突然不确定,如果我也可以,甚至不得不使用相同的TableRowSorter - 实例或如果我必须为每个表创建TableRowSorter。首先,我将这两个表都添加到这两个表中,因为这似乎很实用,但在很多情况下我得到了IndexOutOfBound-Exceptions。经过一番挖掘后,我发现这是因为TableRowSorter在每个TableModelEvent处都会更新两次,因为每个表(RowHeader和MainTable)都会自行通知TableRowSorter关于表格更改。

现在我不确定哪条路是正确的。以下解决方案进入我的脑海:我应该添加第二个TableRowSorter(每个表一个)并同步这些,或者我应该将TableModel包装在RowHeaderTable中并让它不触发任何事件?或者,也许我应该创建我自己的RowHeaderTable,它不会通知Sorters有关更改的内容?

+0

您是否尝试过使用一个单独的行排序为每个表?我知道,你必须保持它的同步,但它可能会让你在最初的障碍 – MadProgrammer

+0

@ymene [请参阅我对RowHeader的看法(两个JTables,两个XxxModels,两个通知器的一个监听器)](http:// stackoverflow .com/a/8187799/714968),只有RowFilter,[你可以尝试应用你自己的RowSorter视图](http://stackoverflow.com/a/16664124/714968),[如果没有成功]( http://stackoverflow.com/a/11280226/714968)然后发布,我认为这必须基于你的[SSCCE](http://sscce.org/),或等待(@camickr),顺便说一句这一个)可能是非常好的问题+1 – mKorbel

+0

你可以在哪里吹SSCCE?我记得有过类似的讨论(但不是结果,也找不到它) - 一个非常简单的例子 - 共享RowSorter - 似乎表现良好。 – kleopatra

回答

3

下面是一个快速(小心:没有正式测试!使用示例工作正常,虽然)一个包装RowSorter的实现。

  • 确实在接收模式的更改通知
  • 代表所有状态查询
  • 听包裹RowSorter的什么,并传播其事件

这是客户的责任与所用的RowSorter的保持在同步在主表中

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

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

的RowSorterWrapper:

/** 
* Wrapping RowSorter for usage (f.i.) in a rowHeader. 
* 
* Delegates all state queries, 
* does nothing on receiving notification of model changes, 
* propagates rowSorterEvents from delegates. 
* 
* Beware: untested! 
* 
* @author Jeanette Winzenburg, Berlin 
*/ 
public class RowSorterWrapper<M> extends RowSorter<M> { 

    private RowSorter<M> delegate; 
    private RowSorterListener rowSorterListener; 

    public RowSorterWrapper(RowSorter<M> delegate) { 
     this.delegate = delegate; 
     delegate.addRowSorterListener(getRowSorterListener()); 
    } 

    /** 
    * Creates and returns a RowSorterListener which re-fires received 
    * events. 
    * 
    * @return 
    */ 
    protected RowSorterListener getRowSorterListener() { 
     if (rowSorterListener == null) { 
      RowSorterListener listener = new RowSorterListener() { 

       @Override 
       public void sorterChanged(RowSorterEvent e) { 
        if (RowSorterEvent.Type.SORT_ORDER_CHANGED == e.getType()) { 
         fireSortOrderChanged(); 
        } else if (RowSorterEvent.Type.SORTED == e.getType()) { 
         fireRowSorterChanged(null);    } 
       } 
      }; 
      rowSorterListener = listener; 
     } 
     return rowSorterListener; 
    } 


    @Override 
    public M getModel() { 
     return delegate.getModel(); 
    } 

    @Override 
    public void toggleSortOrder(int column) { 
     delegate.toggleSortOrder(column); 
    } 

    @Override 
    public int convertRowIndexToModel(int index) { 
     return delegate.convertRowIndexToModel(index); 
    } 

    @Override 
    public int convertRowIndexToView(int index) { 
     return delegate.convertRowIndexToModel(index); 
    } 

    @Override 
    public void setSortKeys(List keys) { 
     // TODO Auto-generated method stub 
     delegate.setSortKeys(keys); 
    } 

    @Override 
    public List getSortKeys() { 
     return delegate.getSortKeys(); 
    } 

    @Override 
    public int getViewRowCount() { 
     return delegate.getViewRowCount(); 
    } 

    @Override 
    public int getModelRowCount() { 
     return delegate.getModelRowCount(); 
    } 

    @Override 
    public void modelStructureChanged() { 
     // do nothing, all work done by delegate 
    } 

    @Override 
    public void allRowsChanged() { 
     // do nothing, all work done by delegate 
    } 

    @Override 
    public void rowsInserted(int firstRow, int endRow) { 
     // do nothing, all work done by delegate 
    } 

    @Override 
    public void rowsDeleted(int firstRow, int endRow) { 
     // do nothing, all work done by delegate 
    } 

    @Override 
    public void rowsUpdated(int firstRow, int endRow) { 
     // do nothing, all work done by delegate 
    } 

    @Override 
    public void rowsUpdated(int firstRow, int endRow, int column) { 
     // do nothing, all work done by delegate 
    } 

}