JTable inside JScrollPane: best height to disable

2019-01-12 08:01发布

问题:

I am using the following code to create JTable inside JScrollPane to show column headers

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

The problem is that I need to compute a height for JScrollPane so the whole JTable can be visible and JScrollBars won't appear. How can I do that?

num changes from 2 to 4 and if it is 4 then scroll bars appear. width is fixed.

回答1:

The basic approach is

  • JTable is-a Scrollable which unfortunately doesn't do too well in calculating a prefScrollable, so you have to do it yourself
  • either use a LayoutManager which lays out all at their pref (f.i. FlowLayout), or implement max in JTable (if you use a resizing but max-respecting manager like BoxLayout)
  • JScrollPane is-a validationRoot, so the revalidate must happen on the parent of the scrollPane

Something like:

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:

converting my comments here to the answer, crazy, crazy, really crazy, everything could be complicating the simple things, by assuming that every rows have got the same size, long methods for columnmodel, expanding methods, have to add column renderer/editor, etc..

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


回答3:

What if you call ?

sp.getColumnHeader().getHeight()