JScrollPane 中的 JTable:禁用滚动条的最佳高度

Posted

技术标签:

【中文标题】JScrollPane 中的 JTable:禁用滚动条的最佳高度【英文标题】:JTable inside JScrollPane: best height to disable scrollbars 【发布时间】:2012-12-07 21:49:22 【问题描述】:

我正在使用以下代码在JScrollPane 内创建JTable 以显示列标题

JTable won't show column headers

String[] columnNames = "header1", "header2", "header2", "header3";
Object[][] data = new Object[num][4];
//feed values into data using for

JTable chart = new JTable(data, columnNames);
chart.setShowVerticalLines(false);
chart.setEnabled(false);
chart.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

JScrollPane sp = new JScrollPane(chart);
sp.setPreferredSize(new Dimension(width, chart.getHeight() + 5));
panel.add(sp);

问题是我需要为JScrollPane 计算一个高度,以便整个JTable 可见,而JScrollBars 不会出现。我该怎么做?

num 从 2 变为 4,如果是 4,则出现滚动条。 width 已修复。

【问题讨论】:

永远不要使用 setXXSize ,这样做总是是错误的。相反,让表格将其 prefScrollable 实现为合理的(f.i. JXTable 从其 visibleRows 属性计算高度)并使用合适的 LayoutManager。 @kleopatra,所以我需要某种getHeight,它为加载的数据提供了首选大小 @Nikolay Kuznetsov JScrollPane 用于将更大的区域减少到可滚动的JViewport,然后必须决定可见行table.setPreferredScrollableViewportSize(new Dimension(width, 12 * rowHeight))max numberJTable.AUTO_RESIZE_OFF 的宽度必须是硬编码的,或者你必须从ColumnModel 计算重量,发疯,发疯,发疯,getPreferredScrollableViewportSize 来自water,没有别的 @mKorbel,我称之为chart.setPreferredScrollableViewportSize(new Dimension(width, num * chart.getRowHeight()));,但它似乎将高度值提高了两倍。 @Nikolay Kuznetsov 我稍后会详细说明,(@kleopatra) 和 (@camickr) 和 get/setPreferredSize 的答案之间的外显, 【参考方案1】:

基本方法是

JTable 是一个 Scrollable,不幸的是它在计算 prefScrollable 方面做得不太好,所以你必须自己做 要么使用一个 LayoutManager,它在它们的首选项(f.i. FlowLayout)中布置所有内容,要么在 JTable 中实现 max(如果您使用像 BoxLayout 这样的调整大小但尊重最大值的管理器) JScrollPane 是一个validationRoot,因此重新验证必须发生在scrollPane 的父级上

类似:

final JTable table = new JTable(10, 5) 

    @Override
    public Dimension getPreferredScrollableViewportSize() 
        Dimension dim = super.getPreferredScrollableViewportSize();
        // here we return the pref height
        dim.height = getPreferredSize().height;
        return dim;
    

;
final JComponent content = new JPanel();
content.add(new JScrollPane(table));
Action add = new AbstractAction("add row") 

    @Override
    public void actionPerformed(ActionEvent e) 
        ((DefaultTableModel) table.getModel()).addRow(new Object[]);
        content.revalidate();
    
;

【讨论】:

【参考方案2】:

在这里将我的 cmets 转换为答案,疯了,疯了,真的疯了,一切都可能使简单的事情复杂化,假设每一行都有相同的大小,columnmodel 的长方法,扩展方法,必须添加列渲染器/编辑器等。

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumn;

public class TablePreferredSize 

    private String[] head = "One", "Two", "Three", "Four", "Five", "Six";
    private String[][] data = new String[25][6];
    private JTable table = new JTable(data, head);
    private DefaultTableColumnModel columnModel = new DefaultTableColumnModel();
    private TableColumn column = new TableColumn();
    private int rowHeight = 23;
    private int rowWidth = 0;

    public TablePreferredSize() 
        table.setRowHeight(23);
        table.setIntercellSpacing(new Dimension(1, 1));
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        column = new TableColumn();
        column.setModelIndex(0);
        column.setHeaderValue("One");
        column.setPreferredWidth(250);
        columnModel.addColumn(column);
        rowWidth += column.getPreferredWidth();
        column = new TableColumn();
        column.setModelIndex(1);
        column.setHeaderValue("Two");
        column.setPreferredWidth(120);
        columnModel.addColumn(column);
        rowWidth += column.getPreferredWidth();
        column = new TableColumn();
        column.setModelIndex(2);
        column.setHeaderValue("Three");
        column.setPreferredWidth(80);
        columnModel.addColumn(column);
        rowWidth += column.getPreferredWidth();
        column = new TableColumn();
        column.setModelIndex(3);
        column.setHeaderValue("Four");
        column.setPreferredWidth(120);
        columnModel.addColumn(column);
        column = new TableColumn();
        column.setModelIndex(4);
        column.setHeaderValue("Five");
        column.setPreferredWidth(70);
        columnModel.addColumn(column);
        column = new TableColumn();
        column.setModelIndex(5);
        column.setHeaderValue("Six");
        column.setPreferredWidth(30);
        columnModel.addColumn(column);
        table.setColumnModel(columnModel);
        table.setPreferredScrollableViewportSize(new Dimension(rowWidth, 12 * rowHeight));
        JScrollPane scrollPane = new JScrollPane(table);
        JFrame frame = new JFrame("Table PreferredSize");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scrollPane);
        frame.pack();
        frame.setVisible(true);
    

    public static void main(String[] args) 
        SwingUtilities.invokeLater(new Runnable() 

            @Override
            public void run() 
                TablePreferredSize t = new TablePreferredSize();
            
        );
    

【讨论】:

setPreferredScrollableViewportSize setXXSize 基本上是一样的——硬编码的尺寸总是邪恶。而且你知道它,但仍在传播......【参考方案3】:

如果你打电话呢?

sp.getColumnHeader().getHeight()

【讨论】:

sp.setPreferredSize(new Dimension(width, sp.getColumnHeader().getHeight() + 5)); 给我NPE 实际上表格将标题添加为 JScrollPane 的列标题,但可能在第一次绘制时知道大小,而不是在初始化表格时。你也可以试试 chart.getTableHeader().getHeight() @NikolayKuznetsov 事后猜测合理(又名:pref)大小是错误的做法,这是 layoutManager 的专属工作 @kleopatra,layoutManager 是什么?面板?什么适合我的情况?我正在为 JPanel 使用 BoxLayout。

以上是关于JScrollPane 中的 JTable:禁用滚动条的最佳高度的主要内容,如果未能解决你的问题,请参考以下文章

JScrollPane不会滚动到JTable的底部

将 JScrollPane 滚动到 JTable 上的特定行 [重复]

如何在 DragAndDrop 期间在 Main-JTable 上绘制 RowHeader-JTable 的 Dropline?

添加 JScrollpane 时框布局中的框未对齐

禁用JTable中的用户编辑

JTable 滚动到指定的行索引