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

StackOverflow https://stackoverflow.com/questions/2548139

Вопрос

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

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

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

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

Это было полезно?

Решение

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

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

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 );

Другие советы

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

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

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

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

Ознакомьтесь с этим классом, извлеченным из 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)

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top