Подтвердить что ты не робот

Включение автоматического изменения размера 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);
            }
        });
    }
}
4b9b3361

Ответ 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.