Add Column Selection to JTables #22
Chapter 3, Tables and Trees
|
107
HACK
When you run this version of ColumnResizer, the table should look like
Figure 3-3.
Having done this, it’s still possible to crush either table cells or headers if
you resize (programatically or by dragging the frame’s corner) to a point
where there’s just not enough room for all the content. If you really wanted
to keep header cells intact, you could alter the previous code to set the
TableColumn’s minimum width to the preferred width of the header cell,
assuming the header isn’t much wider than the content. Ultimately, it’s
really a question of what data you’re putting in the table and what looks
right to you.
Hacking the Hack
“But,” you might be saying, “what if I don’t have my table data in advance?”
If you have some idea of what the data is probably going to be like, you
could create your table, add this “prototype” data as a row, size the col-
umns, and then remove the prototype…all before ever making the table visi-
ble. That would give your users reasonable default sizing, and then they
could resize columns by dragging header borders as desired. Of course, you
could always hook up a
TableModelListener and resize the columns every
time data is inserted, deleted, or updated, but having the column widths
jump around magically can be very annoying.
H A C K
#22
Add Column Selection to JTables Hack #22
So, why can’t I select a column by clicking on its header?
Here’s something that seems strange about JTables: you can click on the col-
umn headers, but only for the purpose of reordering columns—not for
selecting the contents of that column. I don’t know about you, but consider-
ing that I almost never reorder columns, it seems like the default behavior is
Figure 3-3. Accounting for header width in JTable column resizing
108
|
Chapter 3, Tables and Trees
#22 Add Column Selection to JTables
HACK
backward. And if your users have had their expectations set by working with
Excel or other spreadsheets, they’ll surely expect the ability to select an
entire column.
The to-do list for adding column selectability to a
JTable
consists of two
items:
Change which kinds of multiselection are allowed.
Wire up a
MouseListener
.
Example 3-3 shows a very simple implementation.
The constructor is deliberately simple, taking only a two-dimensional array
of contents and a one-dimensional array of headers. Of course,
JTable has
many more constructor signatures than this, but this is the one that will be
easiest to expose to a test class (do I have to mention that building out the
other constructors is left to the reader as an exercise?).
The next step is changing the defaults for multi-cell selection. The default is
to allow row selection—exactly what you don’t want. So, enable column
selection and disable row selection. Next, you want to catch clicks on the
headers so you can select columns in response to them. Unfortunately, the
JTableHeader component doesn’t have an addActionListener( ) method, so
the best you can do is add a
MouseListener instead. Of its various methods,
you only need to override
mouseReleased( ), which signals the end of a click-
and-release.
Example 3-3. A JTable that allows column selection by clicking on column headers
public class ColumnSelectableJTable extends JTable {
public ColumnSelectableJTable (Object[][] items, Object[] headers) {
super (items, headers);
setColumnSelectionAllowed (true);
setRowSelectionAllowed (false);
// set up action listener on table header
final JTableHeader header = getTableHeader( );
header.addMouseListener (new MouseAdapter( ) {
public void mouseReleased (MouseEvent e) {
if (! e.isShiftDown( ))
clearSelection( );
int pick = header.columnAtPoint(e.getPoint( ));
addColumnSelectionInterval (pick, pick);
}
});
}
}

Get Swing Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.