Skip to content

Instantly share code, notes, and snippets.

@Bios-Marcel
Created June 4, 2020 13:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bios-Marcel/ada8781c79b7f13b3e0b3d8486462913 to your computer and use it in GitHub Desktop.
Save Bios-Marcel/ada8781c79b7f13b3e0b3d8486462913 to your computer and use it in GitHub Desktop.
Swing Synchronized Tables
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 );
}
}
import java.util.Comparator;
import java.util.List;
import javax.swing.DefaultRowSorter;
import javax.swing.RowFilter;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
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 );
}
@Override
public void setComparator( int column, Comparator<?> comparator )
{
if ( delegate != null )
{
delegate.setComparatorNonDelegating( column, comparator );
}
super.setComparator( column, comparator );
}
private void setComparatorNonDelegating( int column, Comparator<?> comparator )
{
super.setComparator( column, comparator );
}
@Override
public void setRowFilter( RowFilter<? super M, ? super Integer> filter )
{
if ( delegate != null )
{
delegate.setRowFilterNonDelegating( filter );
}
super.setRowFilter( filter );
}
private void setRowFilterNonDelegating( RowFilter<? super M, ? super Integer> filter )
{
super.setRowFilter( filter );
}
}
import javax.swing.DefaultListSelectionModel;
/**
* Zur Spiegelung der Selektion einer anderen Tabelle. Dieser Wrapper ist nötig, da es sonst
* bei Sortierung, Filterung und Selektion der zu spiegelnden Tabelle zu Fehlern kommt.
*/
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 );
}
@Override
public void addSelectionInterval( final int index0, final int index1 )
{
if ( delegate != null )
{
delegate.addSelectionIntervalNonDelegating( index0, index1 );
}
super.addSelectionInterval( index0, index1 );
}
private void addSelectionIntervalNonDelegating( final int index0, final int index1 )
{
super.addSelectionInterval( index0, index1 );
}
@Override
public void setAnchorSelectionIndex( final int anchorIndex )
{
if ( delegate != null )
{
delegate.setAnchorSelectionIndexNonDelegating( anchorIndex );
}
super.setAnchorSelectionIndex( anchorIndex );
}
private void setAnchorSelectionIndexNonDelegating( final int anchorIndex )
{
super.setAnchorSelectionIndex( anchorIndex );
}
@Override
public void setLeadSelectionIndex( final int leadIndex )
{
if ( delegate != null )
{
delegate.setLeadSelectionIndexNonDelegating( leadIndex );
}
super.setLeadSelectionIndex( leadIndex );
}
private void setLeadSelectionIndexNonDelegating( final int leadIndex )
{
super.setLeadSelectionIndex( leadIndex );
}
@Override
public void setValueIsAdjusting( final boolean isAdjusting )
{
if ( delegate != null )
{
delegate.setValueIsAdjustingNonDelegating( isAdjusting );
}
super.setValueIsAdjusting( isAdjusting );
}
private void setValueIsAdjustingNonDelegating( final boolean isAdjusting )
{
super.setValueIsAdjusting( isAdjusting );
}
@Override
public void clearSelection()
{
if ( delegate != null )
{
delegate.clearSelectionNonDelegating();
}
super.clearSelection();
// Thread.dumpStack();
}
private void clearSelectionNonDelegating()
{
super.clearSelection();
}
// Thread.dumpStack();
@Override
public void insertIndexInterval( final int index, final int length, final boolean before )
{
if ( delegate != null )
{
delegate.insertIndexIntervalNonDelegating( index, length, before );
}
super.insertIndexInterval( index, length, before );
}
private void insertIndexIntervalNonDelegating( final int index, final int length, final boolean before )
{
super.insertIndexInterval( index, length, before );
}
@Override
public void moveLeadSelectionIndex( final int leadIndex )
{
if ( delegate != null )
{
delegate.moveLeadSelectionIndexNonDelegating( leadIndex );
}
super.moveLeadSelectionIndex( leadIndex );
}
private void moveLeadSelectionIndexNonDelegating( final int leadIndex )
{
super.moveLeadSelectionIndex( leadIndex );
}
@Override
public void removeIndexInterval( final int index0, final int index1 )
{
if ( delegate != null )
{
delegate.removeIndexIntervalNonDelegating( index0, index1 );
}
super.removeIndexInterval( index0, index1 );
}
private void removeIndexIntervalNonDelegating( final int index0, final int index1 )
{
super.removeIndexInterval( index0, index1 );
}
@Override
public void removeSelectionInterval( final int index0, final int index1 )
{
if ( delegate != null )
{
delegate.removeSelectionIntervalNonDelegating( index0, index1 );
}
super.removeSelectionInterval( index0, index1 );
}
private void removeSelectionIntervalNonDelegating( final int index0, final int index1 )
{
super.removeSelectionInterval( index0, index1 );
}
@Override
public void setLeadAnchorNotificationEnabled( final boolean flag )
{
if ( delegate != null )
{
delegate.setLeadAnchorNotificationEnabledNonDelegating( flag );
}
super.setLeadAnchorNotificationEnabled( flag );
}
private void setLeadAnchorNotificationEnabledNonDelegating( final boolean flag )
{
super.setLeadAnchorNotificationEnabled( flag );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment