JTable - Teil 7 - Ein Header für die Rows

Status
Nicht offen für weitere Antworten.
B

Beni

Gast
Beni hat gesagt.:
JTable - Teil 7 - Ein Header für die Rows
Standartmässig unterstützt das JTable nur einen Header, der über den Spalten steht.

Es ist aber kein grosses Problem eine Component - TableRowHeader - zu erstellen, welche dem JScrollPane übergeben werden kann auf dem das JTable sitzt.
Dazu wird die Methode JScrollPane#setRowHeader benutzt.

Da man es sich nicht leisten kann, bei jedem Aufruf von paint den gesammten Header neu darzustellen (sobald die Tabelle viele Einträge kriegt (1000 oder mehr), würde enorm viel Zeit in das Zeichnen investiert werden), zeichnet die der Header nur gerade die "Knöpfe", welche auch sichtbar sind.

Da die Spalten einer JTable nicht immer gleichhoch sein müssen, muss der Header jede Spalte einzeln beachten, und nicht einfach eine Rechnung machen, um herauszufinden wo gezeichnet, und wo nicht gezeichnet werden muss.

Das Demoframe. Man beachte, dass der Header dem ScrollPane übergeben werden muss.
Java:
public class JTableDemo {
	public static void main( String[] args ) {
		// Das JTable initialisieren
		Vector title = new Vector();
		title.add( "A" );
		title.add( "B" );
		title.add( "C" );
		title.add( "D" );
		
		JTable table = new JTable( createData(), title );

		// Jede 10. Reihe wird vergrössert, um zu demonstrieren, wie sich der TableRowHeader anpasst.
		int rows = table.getRowCount();
		for( int i = 0; i < rows; i += 10 )
			table.setRowHeight( i, 2*table.getRowHeight( i ) );
		
		JFrame frame = new JFrame( "Demo" );
		JScrollPane pane = new JScrollPane( table );
		
		// mit diesem Befehl wird die Leiste links angesetzt.
		pane.setRowHeader( new TableRowHeader( table, pane ) );
		
		frame.getContentPane().add( pane );
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		frame.pack();
		frame.setVisible( true );
	}
	
	// Produziert genug Daten, dass man scrollen kann.
	private static Vector createData(){
		Vector data = new Vector();
		
		for( int i = 0; i < 10000; i++ ){
			Vector temp = new Vector();
			for( int j = 0; j < 4; j++ )
				temp.add( String.valueOf( Math.random() ) );
			
			data.add( temp );
		}
		
		return data;
	}
}

Der TableRowHeader. Eigentlich nichts weiter als eine ganz normale Component.
Java:
public class TableRowHeader extends JViewport implements AdjustmentListener{
	private JTable	table;
	private Cell cell;

	public TableRowHeader( JTable table, JScrollPane parent ) {
		this.table = table;
		cell = new Cell();
		setView( new Dummy() );
		setPreferredSize( new Dimension( 100, 0 ) );
		
		parent.getVerticalScrollBar().addAdjustmentListener( this );
		parent.getHorizontalScrollBar().addAdjustmentListener( this );
	}
	
	public void adjustmentValueChanged( AdjustmentEvent e ) {
		repaint();
	}

	protected void paintComponent(Graphics g){
		super.paintComponent( g );
		Rectangle rec = TableRowHeader.this.getViewRect();

		int y = 0;
		int rows = table.getRowCount();
		int index = 0;

		if( rows == 0 )
			return;

		if( y + table.getRowHeight( 0 ) < rec.y ){
			while( index < rows ){
				int height = table.getRowHeight( index );

				if( y + height < rec.y ){
					y += height;
					index++;
				}
				else
					break;
			}
		}

		int max = rec.y + rec.height;
		int width = getWidth();

		while( y < max && index < rows ){
			int height = table.getRowHeight( index );
			cell.set( index );
			SwingUtilities.paintComponent( g, cell, this, 0, y-rec.y, width, height );
            
			y += height;
			index++;
		}
	}

	// Nur eine leere Hülle, damit eine "Simulation" aufgebaut werden kann.
	private static class Dummy extends JComponent{
		public void paint( Graphics g ){
			// do nothing
		}

		public void update( Graphics g ) {
			// do nothing
		}
	}
	
	// Stellt den Knopf für eine Reihe dar.
	private class Cell extends JLabel {
		public void set( int row ) {
			setHorizontalAlignment( CENTER );
			setForeground( TableRowHeader.this.getForeground() );
			setBackground( TableRowHeader.this.getBackground() );
			setFont( TableRowHeader.this.getFont() );
			setText( "Row " + row );
			setBorder( UIManager.getBorder( "TableHeader.cellBorder" ) );
		}
	}
}


Und daraus ergibt sich schliesslich dieses Bild:

beni-albums-jtable-picture70-table-15.png


Selbstverständlich könnte man den Header ausbauen. So wäre vielleicht ein verschieben von Zeilen möglich... Ein Beispiel das die Möglichkeiten zeigt gibt es ja: den JTableHeader.

© August 2004
Dieses Tutorial unterliegt dem Copyright, Kopien (auch nur von Teilen) sind nur für nicht-komerzielle Zwecke gestattet; Detailfragen (insbesondere bei Unsicherheiten), bitte direkt an die Autoren.
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben