Включение автоматического изменения размера JTable, только если он соответствует области просмотра

Мне нужно создать JTable внутри JScrollPane с изменяемым размером столбцов (когда пользователь увеличивает ширину столбца - появляется горизонтальная полоса прокрутки). Для этого я использую table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);. Кроме того, когда область просмотра достаточно широка, чтобы содержать всю таблицу, столбцы должны растягиваться, чтобы заполнить ширину области просмотра. Для этого я переопределил метод getScrollableTracksViewportWidth() класса JTable следующим образом:

@Override
public boolean getScrollableTracksViewportWidth() {
    return getPreferredSize().width < getParent().getWidth();
}

Этот подход работает хорошо, за исключением одного: когда я впервые пытаюсь изменить размер столбца, он возвращает собственную ширину в начальное положение. Если я быстро изменю размер столбца и отпущу мышь, таблица продолжит работать нормально. Итак, в чем причина такого поведения? Почему таблица пытается изменить размер, даже если getScrollableTracksViewportWidth() возвращает false? Или, может быть, вы можете предложить лучшее решение для реализации такого режима изменения размера?

Сильфон - простой рабочий пример вышеуказанной проблемы:

import javax.swing.*;

public class TestTable {
    private static Object[][] data = new Object[][] {
            { "a", "b", "c" },
            { "d", "e", "f" }
    };
    private static Object[] colNames = new Object[] { "1", "2", "3" };

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JTable table = new JTable(data, colNames) {
                    @Override
                    public boolean getScrollableTracksViewportWidth() {
                        return getPreferredSize().width < getParent().getWidth();
                    }
                };
                table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

person user2137020    schedule 05.03.2013    source источник


Ответы (1)


Казалось, что логика по умолчанию doLayout() не работала, когда вы пытались увеличить размер столбца, когда горизонтальная полоса прокрутки не была видна, поэтому я избавился от логики по умолчанию и просто принял ширину столбца, не пытаясь настроить Это.

import javax.swing.*;
import javax.swing.table.*;

public class TestTable {
    private static Object[][] data = new Object[][] {
            { "a", "b", "c" },
            { "d", "e", "f" }
    };
    private static Object[] colNames = new Object[] { "1", "2", "3" };

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JTable table = new JTable(data, colNames)
                {
                    @Override
                    public boolean getScrollableTracksViewportWidth()
                    {
                        return getPreferredSize().width < getParent().getWidth();
                    }

                    @Override
                    public void doLayout()
                    {
                        TableColumn resizingColumn = null;

                        if (tableHeader != null)
                            resizingColumn = tableHeader.getResizingColumn();

                        //  Viewport size changed. May need to increase columns widths

                        if (resizingColumn == null)
                        {
                            setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
                            super.doLayout();
                        }

                        //  Specific column resized. Reset preferred widths

                        else
                        {
                            TableColumnModel tcm = getColumnModel();

                            for (int i = 0; i < tcm.getColumnCount(); i++)
                            {
                                TableColumn tc = tcm.getColumn(i);
                                tc.setPreferredWidth( tc.getWidth() );
                            }

                            // Columns don't fill the viewport, invoke default layout

                            if (tcm.getTotalColumnWidth() < getParent().getWidth())
                                setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
                                super.doLayout();
                        }

                        setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
                    }

                };
                table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

Отредактировано для использования AUTO_RESIZE_ALL_COLUMNS.

person camickr    schedule 06.03.2013
comment
См. Также: stackoverflow.com/questions/15499255/ для другой реализации. - person camickr; 20.03.2013
comment
Работает как шарм! Единственное решение, которое я нашел, отлично работает. - person Pratanu Mandal; 14.01.2017