2010-03-30 22 views
9

Qual è il modo migliore per impostare una tabella in un JScrollPane in modo tale che la prima colonna sia sempre sullo schermo nella stessa posizione indipendentemente dallo scorrimento orizzontale e dalle sovrapposizioni delle colonne che passano sotto?Come posso creare una JTable in cui la prima colonna si trova sempre nella finestra di JScrollPane?

Quando la barra di scorrimento si trova all'estrema sinistra, le colonne sembrano normali, ma mentre l'utente scorre verso destra, le colonne secondarie (2 e on) si spostano sotto il primo fino a quando l'ultima colonna appare all'estrema destra del viewport?

Ho trovato un esempio tratto dal libro "Java Swing" di Eckstein che esegue questa operazione, ma non consente il ridimensionamento della prima colonna. Stavo pensando ad uno schema in cui uno JPanel aveva una struttura orizzontale e un tavolo che conteneva le colonne secondarie e un altro JPanel che galleggiava su di esse (fisso indipendentemente dallo scorrimento). La struttura sarebbe quella di mantenere costante l'intervallo di viewport mentre la prima colonna galleggiava intorno. Idealmente potrei farlo con due tabelle usando lo stesso modello, ma non sono sicuro che l'intera idea sia una soluzione ingenua.

Preferirei una configurazione in cui più tabelle si trovano sullo stesso foglio di scorrimento verticalmente, dove tutte le loro prime colonne sono allineate e si muovono insieme e ci sono solo piccoli spazi orizzontali tra le singole tabelle.

risposta

12

Fixed Column Table fa la maggior parte di ciò che ti serve.

Non supporta il ridimensionamento della colonna fissa quindi sarà necessario aggiungere codice come:

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, mi aspettavo la mia domanda per essere più oscura per ottenere una risposta velocemente. Questo dovrebbe funzionare molto bene. Lo proverò con il codice delle colonne ridimensionabili che hai fornito. Grazie. – voodoogiant

1

Penso che tu sia sulla strada giusta. Ciò che si concettualmente ha è una tabella con una "colonna di intestazione" per ogni riga. Vorrei usare due tabelle: una ha la colonna 'più a sinistra' e l'altra ha tutte le altre. Poi li presenterei in un JSplitPane con la tabella 'leftmost column' sulla sinistra e il resto sulla destra. Ci sarebbe una singola barra di scorrimento verticale che controllava l'offset y di entrambe le tabelle e una singola barra di scorrimento orizzontale che controllava il riquadro destro (solo).

È inoltre possibile utilizzare le funzioni avanzate di JScrollPane per impostare un componente "intestazione" a sinistra dell'area di scorrimento principale. Non l'ho mai fatto, ma potresti essere in grado di usarlo come "intestazione" delle tue righe.

4

JScrollPane ha un'area specificamente per questo, l'intestazione di riga (vedere il diagramma nel API :)

Tutto quello che dovete fare è: - creare un JTable in più per questo settore fisso - agganciarlo fino alla prima colonna del modello di dati - impostarlo come l'intestazione di riga - e nella tabella principale omettere o rimuovere la prima colonna di dati.

Quando la finestra di scorrimento scorre su e giù, entrambe le tabelle scorreranno in sincronia senza codice aggiunto. Quando lo scrollpan scorre orizzontalmente, l'intestazione della riga viene sempre mantenuta visibile e scorre solo la tabella principale.

Per la maggior parte dei casi, l'unico codice aggiunto necessario per il ridimensionamento della colonna, come nell'esempio di camickr.

2

Partenza questa classe, estratto da 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()); 
    } 
} 

Successivamente, basta chiamare il metodo di costruzione:

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