2010-03-30 4 views
9

Was ist der beste Weg, um eine Tabelle in einem JScrollPane so einzurichten, dass die erste Spalte immer auf dem Bildschirm an der gleichen Position ist, unabhängig von horizontal scrollenden und überlappenden Spalten, die darunter liegen?Wie kann ich eine JTable erstellen, in der sich die erste Spalte immer im JScrollPane-Ansichtsfenster befindet?

Wenn sich die Bildlaufleiste am weitesten links befindet, sehen die Spalten normal aus, aber wenn der Benutzer nach rechts scrollt, bewegen sich die sekundären Spalten (2 und mehr) unter der ersten, bis die letzte Spalte ganz rechts neben der erscheint Ansichtsfenster?

Ich fand ein Beispiel aus Ecksteins "Java Swing" -Buch, das macht das, aber es erlaubt keine Größenänderung der ersten Spalte. Ich dachte an ein Schema, bei dem ein JPanel eine horizontale Struktur und eine Tabelle mit den sekundären Spalten und einem weiteren JPanel enthielt, das über ihnen schwebte (unabhängig davon, ob sie scrollten). Die Struktur wäre, den Darstellungsbereich konstant zu halten, während die erste Spalte herumschwebt. Idealerweise könnte ich es mit zwei Tabellen machen, die dasselbe Modell verwenden, aber ich bin nicht sicher, ob die ganze Idee eine naive Lösung ist.

Ich würde im Idealfall eine Einrichtung, wo mehrere Tabellen auf der gleichen Scroll-Palette vertikal sind, wo alle ihre ersten Spalten ausgerichtet sind und zusammen bewegen und es gibt nur kleine horizontale Lücken zwischen den einzelnen Tabellen.

Antwort

12

Fixed Column Table macht das meiste von dem, was Sie brauchen.

Es ist nicht die feste Spalte Ändern der Größe nicht unterstützt, so dass Sie Code hinzufügen müßten wie:

MouseAdapter ma = new MouseAdapter() 
{ 
    TableColumn column; 
    int columnWidth; 
    int pressedX; 

    public void mousePressed(MouseEvent e) 
    { 
     JTableHeader header = (JTableHeader)e.getComponent(); 
     TableColumnModel tcm = header.getColumnModel(); 
     int columnIndex = tcm.getColumnIndexAtX(e.getX()); 
     Cursor cursor = header.getCursor(); 

     if (columnIndex == tcm.getColumnCount() - 1 
     && cursor == Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)) 
     { 
      column = tcm.getColumn(columnIndex); 
      columnWidth = column.getWidth(); 
      pressedX = e.getX(); 
      header.addMouseMotionListener(this); 
     } 
    } 

    public void mouseReleased(MouseEvent e) 
    { 
     JTableHeader header = (JTableHeader)e.getComponent(); 
     header.removeMouseMotionListener(this); 
    } 

    public void mouseDragged(MouseEvent e) 
    { 
     int width = columnWidth - pressedX + e.getX(); 
     column.setPreferredWidth(width); 
     JTableHeader header = (JTableHeader)e.getComponent(); 
     JTable table = header.getTable(); 
     table.setPreferredScrollableViewportSize(table.getPreferredSize()); 
     JScrollPane scrollPane = (JScrollPane)table.getParent().getParent(); 
     scrollPane.revalidate(); 
    } 
}; 

JTable fixed = fixedColumnTable.getFixedTable(); 
fixed.getTableHeader().addMouseListener(ma); 
+0

Hrmm, erwartete ich meine Frage Unbekannter zu sein, um eine Antwort zu schnell. Das sollte sehr gut funktionieren. Ich werde es mit dem von Ihnen bereitgestellten skalierbaren Spaltencode versuchen. Vielen Dank. – voodoogiant

1

Ich denke, Sie sind auf dem richtigen Weg. Was Sie konzeptionell haben, ist eine Tabelle mit einer 'Kopfzeile' für jede Zeile. Ich würde zwei Tabellen verwenden - einer hat die 'ganz links' Spalte und der andere hat alle anderen. Dann würde ich diese in einem JSplitPane mit der linken Spalte Spalte auf der linken Seite und dem Rest auf der rechten Seite präsentieren. Es gäbe eine einzelne vertikale Bildlaufleiste, die den y-Versatz beider Tabellen steuert, und eine einzige horizontale Bildlaufleiste, die nur das rechte Fenster steuert.

Sie können auch die erweiterten Funktionen von JScrollPane verwenden, um eine "Header" -Komponente auf der linken Seite des Hauptbereichs festzulegen. Ich habe es noch nie gemacht, aber Sie könnten es vielleicht als 'Kopfzeilen' Ihrer Zeilen verwenden.

4

JScrollPane einen Bereich speziell für diese hat, der Zeilenkopf (das Diagramm in den :)

API sehen

Alles, was Sie tun müssen, ist: - eine zusätzliche JTable für diesen festen Bereich schaffen - Haken es in die erste Spalte Ihrer Datenmodell bis - legen Sie es als den Zeilenkopf - und in der Haupttabelle wegzulassen oder entfernen die erste Spalte der Daten.

Wenn die Bildlaufleiste nach oben und unten scrollt, werden beide Tabellen synchron ohne hinzugefügten Code gescrollt. Wenn die Bildlaufleiste horizontal scrollt, wird der Zeilenkopf immer sichtbar gehalten und nur die Haupttabelle wird gescrollt.

In den meisten Fällen ist der einzige zusätzliche Code, den Sie für die Spaltengrößenänderung benötigen, wie das Beispiel von camickr.

2

Schauen Sie sich diese Klasse, extrahiert aus http://fahdshariff.blogspot.sg/2010/02/freezing-columns-in-jtable.html

import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JViewport; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.JTableHeader; 
import javax.swing.table.TableModel; 
public class FrozenTablePane extends JScrollPane{  
    public FrozenTablePane(JTable table, int colsToFreeze){  
     super(table);  
     TableModel model = table.getModel();  
     //create a frozen model  
     TableModel frozenModel = new DefaultTableModel(         
       model.getRowCount(),         
       colsToFreeze);  
     //populate the frozen model  
     for (int i = 0; i < model.getRowCount(); i++) {  
      for (int j = 0; j < colsToFreeze; j++) {   
       String value = (String) model.getValueAt(i, j);   
       frozenModel.setValueAt(value, i, j);  
      }  
     } 
    //create frozen table 
    JTable frozenTable = new JTable(frozenModel); 
    //remove the frozen columns from the original table 
    for (int j = 0; j < colsToFreeze; j++) { 
    table.removeColumn(table.getColumnModel().getColumn(0)); 
    }  table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 
    //format the frozen table  
    JTableHeader header = table.getTableHeader();  
    frozenTable.setBackground(header.getBackground());  
    frozenTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);  
    frozenTable.setEnabled(false);  
    //set frozen table as row header view 
    JViewport viewport = new JViewport();  
    viewport.setView(frozenTable); 
    viewport.setPreferredSize(frozenTable.getPreferredSize()); 
    setRowHeaderView(viewport); 
    setCorner(JScrollPane.UPPER_LEFT_CORNER, 
      frozenTable.getTableHeader()); 
    } 
} 

Danach einfach den Konstruktor-Methode aufrufen:

JTable table = new JTable(<yourData>, <yourColumns>); 
FrozenTablePane frozenPane = new FrozenTablePane(table,1);//where 1 is the number of freezed column(s) 
Verwandte Themen