JTable: Zwei Tabellen zusammenführen?

Hallo!

Aaaalso, ich hab zwei JTables mit der gleichen Anzahl an Spalten. Ansonsten sind die Dinger aber jeweils recht komplex und haben nix miteinander gemeinsam. Dennoch muss ich beide Tabellen so untereinander darstellen, dass es für den Benutzer aussieht, als handele es sich um eine einzige Tabelle. Weiß jemand, wie ich das bewerkstelligen könnte?
 
Hi Snape,

klar darfst Du. Ich hab zwei Table Models, wobei im ersten Strings mit Checkbox davor gerendert werden, im zweiten Zahlen. Die sind irgendwie aus dem ersten Model herausgerechnet, so eine Art "Summe". Das heißt, die Zellenrenderer sind komplett andere für die beiden Models. Außerdem gibt es auch noch andere Sachen, die verhindern, dass ich die beiden Models zu einem zusammenführe. Z.B. hab ich auf das erste Model einen Listener gesetzt, der mir sagt, wenn sich ein Eintrag ändert. Den kann ich aber in der zweiten "Tabelle", also im zweiten Model, nicht gebrauchen, usw.

Es ist also schon so, dass ich zwei grundverschiedene Tabellen gegeben hab, auch wenn die zweite aus der ersten berechnet ist. Und die will ich halt schön darstellen in einer einzigen Tabelle, damit man die Daten immer schön auf einen Blick hat u.nicht mit dem Auge hin und herspringen muss, wenn man z.B. mit der Maus eine Zeile verschiebt oder sich die Größe einer Spalte in einer der Tabellen ändert.

Dabei kommt mir gerade selbst ein (grauenhafter) Einfall: Ich könnte beide Einzelltabellen untereinander anzeigen und immer Spaltenreihenfolge und -weiten nachverfolgen, und wenn sie sich bei einer ändern, bei der anderen auch ändern. Aber ich dachte an eine schöne Lösung...
 
So spontan meine ich mich zu erinnern, dass bei einer Tabelle ohne Spaltennamen die Zeile mit den Spaltennamen gar nicht erst angezeigt wird. Oder war das bei einer Tabelle, die nicht in eine Scrollpane gelegt wird? Hm, mal ausprobieren.
 
Hi! Hab das Problem bereits gelöst, auch wenn es mich fast den Sonntagnachmittag gekostet hätte... anbei der Code (c) Eques tenebrarum ;)

Code:
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();
 	}
}
 
Zurück