No good user interface and certainly no professional user interface should be
using editable cells in a JTable.
A much better alternative is to use ordinary buttons or menu items,
and possibly a modification dialog (similar to a Windows property
sheet
).
Suppose your table column contains Boolean values, each
representing whether the row object is turned on
or turned off.
Instead of using a table cell editor containing a JCheckBox,
you can just as easily create a JButton or JMenuItem
whose text is Turn On
and another whose text is Turn Off.
This has a major benefit in that it can operate on all the selected rows,
instaed of one at a time. If you needed to check or uncheck dozens
(or hundreds) or rows, would you rather do it one by one using the
JCheckBoxes in cells, or would you rather select all the
applicable rows and press a button?
JCheckBox cell editors are the simplest case. In the
case of other cell editors, or in the case of any table with more than
one editable column, the solution is having a JButton or
JMenuItem which displays a Properties
dialog.
For example, if your table has a Name
column and a
Date
column, then instead of making the cells editable,
you are better off having a Modify
button which
displays a simple dialog containing a
labeled Name
text field and a labeled Date
field. (The
date field can even be a JSpinner, which is known to cause
problems if placed in an editable table cell.)
Example 1. Table with editable boolean cells.
Example 2. Table with boolean cells, modifiable using buttons.
Example 3. Table with various editable values.
Example 4. Table with various values, modifiable using buttons and a dialog.
Common objections to this approach include:
I need editable table cells!
The buttons require an extra mouse click on the user’s part.
Our customer insists that we have as few windows as possible!
Editable table cells are not standard. No platform has a standard,
native user interface component or widget which allows editable table
cells. For this reason, Java has had a hard time defining the
behavior of JTables.
If no platform provides editable table cells, why is JTable
trying to do it? Because a JTable looks like a
spreadsheet. It triggers an immediate visual association with spreadsheets
in most people’s minds. Since it looks like a spreadsheet, most
people have assumed it should act like a spreadsheet. In fact, the
standard keyboard assignments for a JTable reserve a
key for initiating a cell edit which is the same key spreadsheets
have been using as the edit
function for over twenty years.
It was a mistake. The Java design team is quite good, but they do make
mistakes, and this was one of them.
A JTable is not a spreadsheet and never was suitable
as a spreadsheet. It’s time programmers and designers got over it.
Spreadsheet programs are special. The spreadsheet is the entire user
interface, so there are no focus issues. Most if not all spreadsheets
don’t even bother with editable cells for normal entry; they
have a special editing area
above or below the spreadsheet matrix.
In cases where entry fields are placed directly in the spreadsheet, they are
specially tailored controls designed to work with the spreadsheet’s
mouse and keyboard input system.
Without any platform‐native table widgets from which to draw, Java has been forced to define the behavior of editable table cells itself. The behavior encompasses a great many issues, so many that it was inevitable that many of them would be overlooked.
If you have Java installed, try out the above applets. If you want to
check the Use
column of every country which starts with an S,
which approach will make it easier? Clicking on one checkbox at a time,
or selecting the entire range (generally a single click‐and‐drag
gesture) and pressing a Use
button?
A particularly dreadful and unfortunately common user interface
offense is the magic
addition of rows in a table. Instead of
a straightforward Add
or New
button alongside the table,
designers try to come up with some automatic
way of having
new, blank rows appear in the table, usually in response to the user’s
entering data into some other cell. This is unpredictable, unintuitive,
and impossible for the user to undo.
Sometimes designers or programmers try to make deleting rows from a
table as automatic
as the addition of new rows as explained
above. For deletion, the unintuitive nature is even worse; what action
makes sense for triggering it? Usually the only answer is making all
the fields blank.
Often, even people who want to make their tables have magic
addition of rows are forced to fall back on using an ordinary
Delete Selected Rows
button. This highlights the awkwardness
of the magic
addition policy, plus it creates an inconsistency
in the user interface, since addition is done one way and deletion another
way.
There is no different appearance given to an editable table cell that
distinguishes it from a non‐editable table cell. The table becomes an
example of one of the worst sins in user interface design: mystery
meat
navigation. The user has to click on every column to figure out
which are editable. (And no, We’ll tell them about it during
training
is not an acceptable solution; rather, it is an admission
that the user interface is poorly designed.)
Some programmers have tried to address this by using arbitrary colors to show which cells are editable. Usually they choose a gray background. Experienced user interface designers, however, know that color alone should never be used to represent any state. Moreover, setting the background means violating the user’s desktop scheme (and users do not like having their computer’s appearance hijacked by arrogant software). There is, in fact, no acceptable color, because desktop themes don’t define a standard color for editable table cells, because editable table cells aren’t a part of any common user interface library.
Some programmers, instead of using special colors, choose to make editable table cells look exactly like their respective editors, usually by using the editor component as the renderer. This leads to an unwieldy amount of clutter, to the point where the entire table is a matrix of cloned components and any attempt on the part of the user to (subconsciously) make order out of the crowded jumble of lines is a chore at best, and impossible at worst. The more time the user needs to spend squinting at the user interface to sort it out, the less intuitive it is.
To make matters worse, JTables don’t have room for
the editor components, so they are squashed and often their text is clipped.
To compensate for this, some programmers increase the height of every row
in the JTable.
All in all, it’s a solution, but not a good solution. It also ends up requiring considerably more work to implement than just using simple buttons or menu items.
Using the keyboard, it’s difficult but possible to edit cells without altering the table’s selection—provided the user knows the key to trigger a cell edit.
Using the mouse, however, it is impossible.
JTable’s default row height
doesn’t leave room for editors.
Because JTable was designed for String and
Boolean editors, they barely fit into the default row
height. Most other cell editors will be clipped, including
JComboBoxes. (You can see it for yourself in the
Example 3 applet above; in any cell whose value is Gray,
start editing and notice the y
is cut off at the bottom.)
Since editable cells are not a standard user interface on any major platform,
there is no definition of which keys should trigger a cell edit, or which
keys should complete or cancel a cell edit. For some editors, typing a
space starts editing. For some (such as text fields), typing any character
starts it. All cell editors can be started using F2,
the same key used by spreadsheets—strong evidence that, as stated above,
someone involved in JTable’s design had
the misguided idea that since a JTable looks like a spreadsheet,
it should act like a spreadsheet.
The most obvious choice, Enter, never starts a
cell edit. Instead, it is part of JTable’s navigation
key set.
Textfield‐based editors start editing with a double‐click of the mouse. Other editors start with a single click of the mouse. Programmers can figure this out, but it’s a cruel joke to play on ordinary users.
JTextField edit keys
conflict with JTable.
Pressing Home or End
in the default cell editor for all classes (other than Boolean)
does not move the text cursor, but instead moves the focus to the
start or end of the current JTable row.
JFormattedTextField or JSpinner.
JTable redirects focus in strange ways when handling its
editors. This is in fact the reason the
getSurrendersFocusOnKeystroke() and
setSurrendersFocusOnKeystroke(boolean) methods were
eventually added to JTable.
JFormattedTextField is an extremely useful class, but its
use of keys and focus makes it difficult to use as an effective
table cell editor. JSpinner’s use
JFormattedTextFields internally and so are subject
to the same limitation.
Although some trial and error will reveal that cells are committed when focus moves to another cell, it becomes more complicated if the cell editor reports that its contents are invalid and cannot be committed. Does the cell just abandon its contents and halt the editing? Does it force the editor to stay active, so that no other cell may be edited?
JTable.
Trial and error will show that editing is neither canceled nor committed
when focus moves to component other than the JTable, but
this behavior is not guaranteed. An application which relies on user
entry needs to be aware that data which the user thought was
finished
may not be a part of the table’s underlying
TableModel.
Trial and error will show that editing is canceled on any editor in a column being moved. This makes sense, but it is not guaranteed behavior.
TableModel.
This situation should never arise, as it is poor user interface design to have a value change while the user is working on it. Most users would find it disorienting and frustrating. Nevertheless, it needs to be addressed. The situation could, conceivably, be much worse: The type of the cell’s column could change during editing, or the editor itself could be changed.