Как я могу создать JTable, где первый столбец всегда находится в области просмотра JScrollPane? - PullRequest
9 голосов
/ 30 марта 2010

Каков наилучший способ настроить таблицу в JScrollPane так, чтобы первый столбец всегда находился на экране в одном и том же положении независимо от горизонтальной прокрутки и перекрытия столбцов, проходящих под ним?

Когда полоса прокрутки находится в самом дальнем левом углу, столбцы выглядят нормально, но когда пользователь выполняет прокрутку вправо, дополнительные столбцы (2 и вкл.) Перемещаются под первым, пока последний столбец не появится в крайнем правом углу области просмотра ?

Я нашел образец, взятый из книги "Java Swing" Экштейна, который как бы делает это, но не позволяет изменить размер первого столбца. Я думал о какой-то схеме, в которой один JPanel содержал горизонтальную структуру, а таблица содержала вторичные столбцы, а другая JPanel - над ними (фиксированная независимо от прокрутки). Структура должна поддерживать постоянный диапазон области просмотра при перемещении первого столбца. В идеале я мог бы сделать это с двумя таблицами, используя одну и ту же модель, но я не уверен, что вся идея - наивное решение.

В идеале я бы хотел установку, в которой несколько таблиц находятся на одной и той же полосе прокрутки по вертикали, где все их первые столбцы выровнены и перемещены вместе, и между отдельными таблицами есть только небольшие горизонтальные промежутки.

Ответы [ 4 ]

12 голосов
/ 31 марта 2010

Таблица фиксированных столбцов делает большую часть того, что вам нужно.

Он не поддерживает изменение размера фиксированного столбца, поэтому вам нужно добавить код вроде:

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 );
5 голосов
/ 31 марта 2010

JScrollPane имеет область специально для этого, заголовок строки (см. Схему в API :)

Все, что вам нужно сделать, это: - создать дополнительный JTable для этой фиксированной области - подключите его к первому столбцу вашей модели данных - установить его в качестве заголовка строки - и в основной таблице пропустите или удалите первый столбец данных.

Когда прокрутка прокручивается вверх и вниз, обе таблицы синхронизируются без добавления кода. Когда полоса прокрутки прокручивается горизонтально, заголовок строки всегда остается видимым, и прокручивается только основная таблица.

В большинстве случаев единственный добавленный код, который вам понадобится, - это изменение размера столбца, как в примере с camickr.

2 голосов
/ 11 марта 2015

Проверить этот класс, извлеченный из 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()); 
    }
}

После этого просто вызовите метод конструктора:

JTable table = new JTable( <yourData>, <yourColumns> );
FrozenTablePane frozenPane = new FrozenTablePane(table,1);//where 1 is the number of freezed column(s)
1 голос
/ 31 марта 2010

Я думаю, вы на правильном пути. Концептуально у вас есть таблица с «столбцом заголовка» для каждой строки. Я бы использовал две таблицы - одна имеет самый левый столбец, а другая - все остальные. Затем я представил бы их в JSplitPane с таблицей «крайнего левого столбца» слева, а остальные - справа. Будет одна вертикальная полоса прокрутки, управляющая смещением y обеих таблиц, и одна горизонтальная полоса прокрутки, управляющая правой панелью (только).

Вы также можете использовать расширенные функции JScrollPane, чтобы установить компонент заголовка слева от основной области прокрутки. Я никогда не делал этого, но вы могли бы использовать это как «заголовки» ваших строк.

...