【发布时间】:2020-09-23 12:50:05
【问题描述】:
我一直在尝试获得两个在排序和过滤 (RowSorter) 和选择 (SelectionModel) 方面基本上完全同步的表。为了实现这一点,我做了两个类。
这些是SelectionModel 和RowSorter 的包装类。他们基本上只是委托每个改变状态的公共方法。您可以在下面看到它们的缩短版本,其中仅包含一个被覆盖的 setter。但是,所有其他的也会被覆盖。我不想过分夸大这个问题。
MirrorableRowSorter(缩写):
public class MirrorableRowSorter<M extends TableModel> extends TableRowSorter<M>
{
private MirrorableRowSorter<M> delegate;
/**
* @param delegate the delegate to set
*/
public void setDelegate( MirrorableRowSorter<M> delegate )
{
this.delegate = delegate;
}
@Override
public void setSortKeys( List<? extends SortKey> sortKeys )
{
if ( delegate != null )
{
delegate.setSortKeysNonDelegating( sortKeys );
}
super.setSortKeys( sortKeys );
}
private void setSortKeysNonDelegating( List<? extends SortKey> sortKeys )
{
super.setSortKeys( sortKeys );
}
//... other methods
}
MirrorableSelectionModel(缩写):
public class MirrorableSelectionModel extends DefaultListSelectionModel
{
private MirrorableSelectionModel delegate = null;
/**
* @param delegate the delegate to set
*/
public void setDelegate( final MirrorableSelectionModel delegate )
{
this.delegate = delegate;
}
@Override
public void setSelectionInterval( final int index0, final int index1 )
{
if ( delegate != null )
{
delegate.setSelectionIntervalNonDelegating( index0, index1 );
}
super.setSelectionInterval( index0, index1 );
}
private void setSelectionIntervalNonDelegating( final int index0, final int index1 )
{
super.setSelectionInterval( index0, index1 );
}
//... other methods
总有一种委托和非委托方法。我这样做是为了避免两个对象之间的乒乓。
然后我用两个表写了一个小例子:
import java.awt.BorderLayout;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.RowFilter;
public class ExampleMirroredTables
{
public static void main( String[] args )
{
JFrame frame = new JFrame();
frame.setLayout( new BorderLayout() );
final JTable tableOne = new JTable( new Object[][]{
new Object[]{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "2", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "3", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "4", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "5", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "6", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "7", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "8", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "9", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "10", "2", "3", "4", "5", "6", "7", "8", "9", "10" }
}, new Object[]{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" } );
final JTable tableTwo = new JTable( new Object[][]{
new Object[]{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "2", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "3", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "4", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "5", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "6", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "7", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "8", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "9", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
new Object[]{ "10", "2", "3", "4", "5", "6", "7", "8", "9", "10" }
}, new Object[]{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" } );
final MirrorableSelectionModel mirrorModelOne = new MirrorableSelectionModel();
final MirrorableSelectionModel mirrorModelTwo = new MirrorableSelectionModel();
mirrorModelOne.setDelegate( mirrorModelTwo );
mirrorModelTwo.setDelegate( mirrorModelOne );
tableOne.setSelectionModel( mirrorModelOne );
tableTwo.setSelectionModel( mirrorModelTwo );
final MirrorableRowSorter mirrorSorterOne = new MirrorableRowSorter();
final MirrorableRowSorter mirrorSorterTwo = new MirrorableRowSorter();
mirrorSorterOne.setDelegate( mirrorSorterTwo );
mirrorSorterTwo.setDelegate( mirrorSorterOne );
mirrorSorterOne.setModel( tableOne.getModel() );
mirrorSorterTwo.setModel( tableTwo.getModel() );
tableOne.setRowSorter( mirrorSorterOne );
tableTwo.setRowSorter( mirrorSorterTwo );
JButton filterButton = new JButton( "Filter randomize" );
AtomicBoolean even = new AtomicBoolean( true );
filterButton.addActionListener( __ ->
{
even.set( !even.get() );
System.out.println( Arrays.toString( tableOne.getSelectedRows() ) );
mirrorSorterTwo.setRowFilter( new RowFilter()
{
@Override
public boolean include( Entry entry )
{
final int moduloResult = ((Integer) entry.getIdentifier()) % 2;
return even.get() ? moduloResult == 0 : moduloResult != 0;
}
} );
System.out.println( Arrays.toString( tableOne.getSelectedRows() ) );
} );
frame.add( filterButton, BorderLayout.NORTH );
frame.add( tableOne, BorderLayout.WEST );
frame.add( new JLabel( " THE MIRROR " ), BorderLayout.CENTER );
frame.add( tableTwo, BorderLayout.EAST );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
如果您使用该选择,您将能够看到,它始终会完美反映。但是,如果您现在在选择所有行 (Ctrl+A) 后点击顶部的过滤器按钮,则在 10 个选定行中,将仅保留索引 0 和 1。我不仅想保留 10 个中已过滤的 5 个,还希望保留其他(现在隐藏)的,并且在再次更改过滤器后仍然可以看到选择。这样做的原因是,我们有一个模仿树的 JTable。如果我们折叠该树中的一个项目并预先选择了父项和它的子项,我们希望在再次展开父项后它们仍然被选中。我认为这是可能的,因为这在使用镜像选择模型时似乎有效,但我不确定为什么。
我不太确定我想要实现的目标是否可能,如果是,我不知道我是否采取了正确的方法。
这里是所有文件的要点:https://gist.github.com/Bios-Marcel/ada8781c79b7f13b3e0b3d8486462913
如果有用于同步表的现有事物(库),我也愿意研究一下。
【问题讨论】:
-
嗨马塞尔。我想你会更新这个问题 - 你打算继续这样做,还是不需要更多答案?
-
我有点纠结于其他事情,所以我暂时不关注这个问题。如果我再次关注它并找到解决方案,我会 100% 在这里发布。
-
不用担心。如果您需要重新打开它,请联系我,我可以帮助您重新打开它。
标签: java swing jtable filtering selection