import javax.swing.table.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
/**
* Use this class to synchronize the view of related tables with the same number of columns.
*
* The TickTableController keeps track of the cell widths and order of the given tables (via constructor parameter JTable[]) by listening to mouseReleased events, and synchronizes the tables.
* In doing so the first table t[0] is used as a reference. Particularly note that changes to the other tables will take no effect (internally, they'll be undone).
*/
public class TickTableController implements MouseListener{
private JTable[] t;
/**
* @param t Die zu verwaltenden Tabellen. Die mit t übergebenen Tabellen müssen in der Anzahl der Spalten übereinstimmen.
*/
public TickTableController(JTable[] t){
this.t = t;
for(int i=0; i<t.length; i++) t[i].getTableHeader().addMouseListener(this); //Add a mouse listener to each table header
}
/**
* Setzt die Reihenfolge der Spalten sowie deren Breite für alle Tabellen auf die durch die erste vorgegebenen Werte.
* Wird automatisch nach einem mouseReleased-Event auf einen Table header aufgerufen.
*/
public void synchronize(){ //Alle anderen richten sich nach der ersten Tabelle, t[0].
for(int i=0; i<t[0].getColumnCount(); i++){
TableColumn col1 = t[0].getColumn(t[0].getColumnName(i));
int index1 = col1.getModelIndex();
int width1 = col1.getWidth();
//System.out.println(index1);
//System.out.println(width1);
for(int k=1; k<t.length; k++){ //Für jede weitere Tabelle
//Idee: Suche die Spalte mit dem Model index index1 und gucke, wo sie auf dem Bildschirm ist.
TableColumn colk = null;
int indexk = -1;
int j = -1;
for(j=i; j<t[k].getColumnCount(); j++){
colk = t[k].getColumn(t[k].getColumnName(j));
indexk = colk.getModelIndex();
if(index1 == indexk) break;
}
//System.out.println("Col mit model index " + index1 + " ist momemtan an pos " + j);
//System.out.println((i == j) + " -- i = " + i + ", j = " + j);
if(i != j) t[k].moveColumn(j,i); //Ändert nichts am Model, nur am View. Bei moveColumn stört mich, dass in der Dokumentation steht, um Platz zu machen wird nicht immer der Rest nach rechts verschoben, sondern manchmal auch nach links. Aber das ist bestimmt nur so dahin geredet, und ich überhöre es.
//Jetzt sollte die i-te Spalte überall an der gleichen Position sein, so dass wir nur noch sicherstellen müssen, dass die Spalte in allen Tabellen die gleiche Breite hat.
int widthk = colk.getWidth();
if(width1 != widthk) colk.setPreferredWidth(width1);
}
}
}
/* *************************************************************************
* Test
*
* Next thing to do is to provide a TickTableControllerPanel, that keeps
* track of the horizontal scrollbars from the JScrollPanes the tables are
* included in.
*/
public static void main(String argv[]){
//Setting up test table 1
String[] cols1 = {"a","b","c"};
Object[][] data1 = {
{"a1","b1","c1"},
{"a2","b2","c2"},
};
JTable table1 = new JTable(data1,cols1);
table1.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
//Setting up test table 2
String[] cols2 = {"Sum a","Sum b","Sum c"};
Object[][] data2 = {
{"3","3","3"},
};
JTable table2 = new JTable(data2,cols2);
table2.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
//Setting up a test table controller
TickTableController controller = new TickTableController(new JTable[]{ table1, table2 });
//Setting up a test frame
//So funktioniert es wunderbar :-) Aber in meinem Fall müssen die Tabellen in Scrollpanes sein, weil die Originaltables auch Row header besitzen, die dargestellt werden müssen.
/*
Box boxP = new Box(BoxLayout.Y_AXIS);
boxP.add(table1.getTableHeader());
boxP.add(table1);
boxP.add(table2);
JScrollPane boxJsp = new JScrollPane(boxP);
*/
//Egal, erstmal irgendwas zum testen:
JSplitPane boxJsp = new JSplitPane(JSplitPane.VERTICAL_SPLIT,new JScrollPane(table1),new JScrollPane(table2));
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,300);
frame.getContentPane().add(boxJsp);
frame.setVisible(true);
}
/* *************************************************************************
* MouseListener methods
*/
public void mouseClicked(MouseEvent e){
//System.out.println("MouseListener: mouseClicked");
}
public void mouseEntered(MouseEvent e){
//System.out.println("MouseListener: mouseEntered");
}
public void mouseExited(MouseEvent e){
//System.out.println("MouseListener: mouseExited");
}
public void mousePressed(MouseEvent e){
//System.out.println("MouseListener: mousePressed");
}
public void mouseReleased(MouseEvent e){
//System.out.println("MouseListener: mouseReleased");
synchronize();
}
}