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

Java 如何使用RowHeader处理JTables中的RowSorter同步?,java,swing,jtable,tablerowsorter,rowheader,Java,Swing,Jtable,Tablerowsorter,Rowheader,以下情况:我有一个带有RowHeader的J(X)表(作为guidline,我使用了一个Rob Camicks great)。一切如期进行 根据要求,我从服务器接收的数据已经包含一个tablerownumber,我必须在rowheader中显示它,并且数据应该是可过滤的。所以我扩展了这个示例,并添加了一个过滤器。过滤视图时,我在行号中看到了间隙(例如:1、3、6、…),这是理想的效果 为了能够根据我自己的tablerow对表进行筛选和排序,我添加了一个。我开始感到困惑。该示例对mainTabl

以下情况:我有一个带有RowHeader的J(X)表(作为guidline,我使用了一个Rob Camicks great)。一切如期进行

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

为了能够根据我自己的tablerow对表进行筛选和排序,我添加了一个。我开始感到困惑。该示例对mainTable和rowHeaderTable使用相同的TableModel和SelectionModel:

setModel( main.getModel() );
setSelectionModel( main.getSelectionModel() );
这很好,因为我不必同步它们。但是关于
TableRowSorter
,我突然不确定我是否也可以或者甚至必须使用相同的
TableRowSorter
-实例,或者是否必须为每个表创建一个
TableRowSorter
。首先,我在两个表中都添加了相同的内容,因为这看起来很实际,但在许多情况下,我得到了
indexootfound异常。经过一番挖掘,我发现这是因为
TableRowSorter
在每次
TableModelEvent
时都会更新两次,因为每个表(RowHeader和MainTable)都会通知
TableRowSorter

现在我不确定该走哪条路。我想到了以下解决方案:我应该添加第二个TableRowSorter(每个表一个)并同步它们,还是应该将TableModel包装在RowHeaderTable中,让它不触发任何事件?或者我应该创建我自己的RowHeaderTable,它根本不通知分拣机更改

这里有一个快速(注意:没有经过正式测试!不过使用示例很好)的包装行分拣器实现

  • 接收模型更改通知时不执行任何操作
  • 委派所有状态查询
  • 侦听包装的行分类器并传播其事件
客户有责任使其与主表中使用的行分拣机保持同步

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

public void interactiverowSorterRapperSharedXtable(){
final DefaultTableModel tableModel=新的DefaultTableModel(list.getElementCount(),2){
@凌驾
公共类getColumnClass(int columnIndex){
返回Integer.class;
}
};
对于(int i=0;i
说唱歌手:

/**
 * 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.convertRowIndexToView(index);
    }

    @Override
    public void setSortKeys(List keys) {
        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
    }

}
/**
*包装行分拣机,以便在行标头中使用(f.i.)。
* 
*委托所有状态查询,
*在收到模型更改通知时不执行任何操作,
*传播来自代理的行。
* 
*注意:未经测试!
* 
*@作者Jeanette Winzenburg,柏林
*/
公共类RowsorterRapper扩展RowSorter{
私人分拣员代表;
私人RowsterListener RowsterListener;
公共行分拣机操作员(行分拣机代表){
this.delegate=委托;
addRowSorterListener(getRowSorterListener());
}
/**
*创建并返回重新激发接收的RowSorterListener
*事件。
* 
*@返回
*/
受保护的RowSorterListener getRowSorterListener(){
if(rowSorterListener==null){
RowSorterListener=新的RowSorterListener(){
@凌驾
公共无效分拣机已更改(第e行){
if(rowsortrevent.Type.SORT\u ORDER\u CHANGED==e.getType()){
fireSortOrderChanged();
}else if(rowsortrevent.Type.SORTED==e.getType()){
/**
 * 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.convertRowIndexToView(index);
    }

    @Override
    public void setSortKeys(List keys) {
        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
    }

}