JavaSwingJTable and TableModel: JTable scrolling


JTable scrolling

The code presented here makes use of the general scrolling methods in Scrolling.java and adds arithmetic with the Rectangles obtained from JTable.getCellRect(). All code presented (slightly augmented) and the code omitted here is available in JTableScrolling.java.

The code for rows and columns is completely analogous, usually the row variant is shown. The examples here omit precondition checking.

See fixed JTable for a slight improvement of getCellRect (only matters with RTL layout).

Most example code uses true as third argument for getCellRect() for simplicity. This usually looks better, but it can all be done in the same way with false.

After changing the TableModel (or row heights), the JTable may not immediately have its new size updated. Scrolling code (or any code that has to

do with dimensions or areas of the JTable) should be wrapped in SwingUtilities.invokeLater() [1].

Accessing cells/row/column bounds

This actually has nothing directly to do with scrolling, but the result rectangles are exactly those that are used by the scrolling methods later.

Single cell rectangles are obtained by table.getCellRect(row, column, true).

For complete rows or columns or multiple cells it gets a little harder. Single row:

public Rectangle getRowBounds(JTable table, int row)
{
Rectangle result = table.getCellRect(row, -1, true);
Insets i = table.getInsets();

result.x = i.left;
result.width = table.getWidth() - i.left - i.right;

return result;
}

or for multiple rows:

public Rectangle getRowBounds(JTable table, int first, int last)
{
Rectangle result = table.getCellRect(first, -1, true);
result = result.union(table.getCellRect(last, -1, true));
Insets i = table.getInsets();

result.x = i.left;
result.width = table.getWidth() - i.left - i.right;

return result;
}

Making cells/rows/columns visible

Single cells can be made visible with table.scrollRectToVisible(table.getCellRect(row, column, true));

For rows/columns or cell ranges the actual works can be delegated to Scrolling. You only need to get the rectangle in question.

public static void makeRowVisible(JTable table, int row)
{
Scrolling.scrollVertically(table, getRowBounds(table, row));
}
public static void makeRowsVisible(JTable table, int first, int last, int bias)
{
Scrolling.scrollVertically(table, getRowBounds(table, first, last), bias);
}

and completely analogous for columns.

Making cells/rows/columns centered

See general scrolling discussion.

public static void centerRow(JTable table, int row)
{
Scrolling.centerVertically(table, getRowBounds(table, row), false);
}

Testing whether cells/rows/columns are visible

public static boolean areRowsVisible(JTable table, int first, int last)
{
return Scrolling.isVerticallyVisible(table, getRowBounds(table, first, last));
}

[1] Bug report (#4172618). One could argue that the JTable should relayout itself automatically (lazily) when something that affects sizes (like adding/removing columns/rows) has been done, and it is asked for the value of such a property. Maybe this is too difficult to do in a consistent way, since multiple components and models are concerned.


(C) 2001-2009 Christian Kaufhold (swing@chka.de)