2010-03-30 49 views
9

¿Cuál es la mejor manera de configurar una tabla en un JScrollPane de forma tal que la primera columna esté siempre en la pantalla en la misma posición independientemente del desplazamiento horizontal y se superponga a las columnas que pasan debajo?¿Cómo puedo crear una JTable donde la primera columna está siempre en la ventana JScrollPane?

Cuando la barra de desplazamiento está en el extremo izquierdo, las columnas parecen normales, pero a medida que el usuario se desplaza hacia la derecha, las columnas secundarias (2 y siguientes) se mueven debajo del primero hasta que aparece la última columna en el extremo derecho del ventana gráfica?

Encontré una muestra tomada del libro "Swing de Java" de Eckstein que hace esto de alguna manera, pero no permite cambiar el tamaño de la primera columna. Estaba pensando en un esquema en el que un JPanel tenía una estructura horizontal y una tabla que contenía las columnas secundarias y otro JPanel que flotaba sobre ellas (fijo independientemente del desplazamiento). La estructura sería mantener el rango de ventana gráfica constante mientras la primera columna flotaba alrededor. Idealmente podría hacerlo con dos tablas usando el mismo modelo, pero no estoy seguro de si la idea es una solución ingenua.

Lo ideal es que me guste una configuración donde varias tablas se encuentren en el mismo panel verticalmente vertical, donde todas las primeras columnas estén alineadas y se muevan juntas y haya pocos espacios horizontales entre las tablas individuales.

Respuesta

12

Fixed Column Table hace la mayor parte de lo que necesita.

No es compatible con el cambio de tamaño de la columna fija lo que sería necesario añadir un código como:

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, esperaba que mi pregunta sea más oscuro para obtener una respuesta de forma rápida. Eso debería funcionar extremadamente bien. Lo intentaré con el código de columnas redimensionables que proporcionó. Gracias. – voodoogiant

1

Creo que está en el camino correcto. Lo que tienes conceptualmente es una tabla con una 'columna de encabezado' para cada fila. Usaría dos tablas: una tiene la columna "más a la izquierda" y la otra tiene todas las demás. Luego los presentaría en un JSplitPane con la tabla 'columna más a la izquierda' a la izquierda y el resto a la derecha. Habría una sola barra de desplazamiento vertical que controlaba el desplazamiento y de ambas tablas, y una barra de desplazamiento horizontal única que controla el panel de la derecha (solo).

También puede usar las características avanzadas de JScrollPane para establecer un componente 'encabezado' a la izquierda del área de desplazamiento principal. Nunca lo hice, pero es posible que pueda usarlo como los 'encabezados' de sus filas.

4

JScrollPane tiene un área específicamente para esto, el encabezado de la fila (ver el diagrama en el API :)

Todo lo que necesita hacer es: - crear un JTable extra por este área fija - conectarlo a la primera columna de su modelo de datos - establecerlo como el encabezado de fila - y en el principal omitir mesa o eliminar la primera columna de datos.

Cuando el panel de desplazamiento se desplaza hacia arriba y hacia abajo ambas tablas se desplazarán en sincronización sin ningún código agregado. Cuando el panel de desplazamiento se desplaza horizontalmente, el encabezado de la fila siempre se mantiene visible y solo se desplaza la tabla principal.

En la mayoría de los casos, el único código agregado que necesitará es el cambio de tamaño de la columna, como el ejemplo de Camickr.

2

Salida esta clase, extraído de 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()); 
    } 
} 

A partir de entonces, simplemente llame al método constructor:

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