2

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.

Community
  • 1
  • 1
Nikolay Kuznetsov
  • 9,467
  • 12
  • 55
  • 101
  • 1
    don't use setXXSize **ever**, that's **always** the wrong thing to do. Instead, let the table implement its prefScrollable to something reasonable (f.i. JXTable calculates the height from its visibleRows property) and use a suitable LayoutManager. – kleopatra Dec 20 '12 at 13:56
  • @kleopatra, so I need some kind of `getHeight` which gives preferredSize for loaded data – Nikolay Kuznetsov Dec 20 '12 at 13:59
  • @Nikolay Kuznetsov `JScrollPane` is there for reducing larger area to the scrolable `JViewport`, then have to decide about `max number` of visible rows `table.setPreferredScrollableViewportSize(new Dimension(width, 12 * rowHeight))`, width for `JTable.AUTO_RESIZE_OFF` must be hardcoded, or you ahve to calculating wight from `ColumnModel`, crazy, crazy, crazy, `getPreferredScrollableViewportSize` from `water`, nothing else – mKorbel Dec 20 '12 at 15:00
  • @mKorbel, I call this `chart.setPreferredScrollableViewportSize(new Dimension(width, num * chart.getRowHeight()));` but it seems to give height twice larger value. – Nikolay Kuznetsov Dec 21 '12 at 08:24
  • @Nikolay Kuznetsov I'll eleborating later, something penetrance betweens answers here by (@kleopatra) and (@camickr) and `get/setPreferredSize`, – mKorbel Dec 21 '12 at 10:01
  • why do you insist on doing it the wrong way (setPrefScrollableSize is just a bad as any of the other setXXSize)? Instead, _implement_ it to do the calcs (btw, `rowCount * rowHeight` _should work_ and does here, if it doesn't in your context, something else is wrong) – kleopatra Dec 21 '12 at 10:45

3 Answers3

9

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();
    }
};
kleopatra
  • 51,061
  • 28
  • 99
  • 211
1

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..

enter image description here

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();
            }
        });
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
0

What if you call ?

sp.getColumnHeader().getHeight()
StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • `sp.setPreferredSize(new Dimension(width, sp.getColumnHeader().getHeight() + 5));` give me NPE – Nikolay Kuznetsov Dec 20 '12 at 11:40
  • Actually table adds header as JScrollPane's column header but may be the size is known on first paint not when the table is initialized. You can also try chart.getTableHeader().getHeight() – StanislavL Dec 20 '12 at 12:56
  • @NikolayKuznetsov it's simply the wrong thingy to do to second-guess a reasonable (aka: pref) size, that's the exclusive job a the layoutManager – kleopatra Dec 20 '12 at 14:00
  • @kleopatra, layoutManager of what? JPanel? What would be a suitable for my case? I am using BoxLayout for JPanel. – Nikolay Kuznetsov Dec 20 '12 at 14:05