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

мне нужно создать JTable внутри JScrollPane с изменяемыми размерами столбцами (когда пользователь увеличивает ширину столбца - появляется горизонтальная полоса прокрутки). Для этого у меня есть use 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);
            }
        });
    }
}

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.