Hi,
Another question. I am developing an application to help users practice
their Chinese vocabulary. Part of the application is a "dictionary
editor", that allows the users to enter the vocabulary in the first
place. The dictionary editor is essentially a JTable. The first column
holds the word in English, the second in Chinese characters, and the
third in pinyin ("romanisation" of the Chinese characters).
Obviously, to be able to enter Chinese characters, the user needs an
input method. So, I derived a class from JTable that switches the
Chinese input method on and off, depending on the column the user is
currently editing.
This all works fine, with one caveat: when the user double clicks in a
table cell, and then starts typing Chinese (using the input method),
everything works fine. However, if the user navigates to a cell using
the arrow keys, and then starts typing in the cell (without first
double clicking in the cell), the system crashes. This happens even in
the most basic JTable example, taken from the Sun Java tutorials, with
the input method enabled all the time (rather than switching it on and
off).
After some experimenting, it turns out that the problem is that the
input method crashes, when (a) the user starts typing something with
the input method enabled, and (b) the JComponent that currently has
focus does not accept text input.
So what is the core of the problem? I derived a class from JTextField
that behaves exactly like JTextField, but implements FocusListener, and
prints to stdout when it gains and loses focus. It turns out that when
the user double-clicks in a cell of the JTable, the JTextField properly
gets focus, and loses focus again when the user finishes editing.
However, when the user starts editing a cell simply by starting typing
(without double clicking in the cell first), the JTextField neither
gains nor loses focus - causing the input method to crash.
Is there any way around this? It is very annoying for the user to have
to double click in every cell he wants to edit, especially if he or she
is entering large dictionaries. I do not know how to make the
JTextField properly gain and lose focus. I have tried to override
getCellEditor() in JTable, call super.getCellEditor(), and then call
requestFocus() on the component returned by super.getCellEditor(), but
that didn't work.
(I'm using Java 1.5; on Windows, I'm using the host system input method
(Microsoft IM), and on Linux I'm using the pinyin input method written
by Erik Peterson,
http://www.chinesecomputing.com/programming/java.html).
Any hints would be appreciated,
Thanks,
Edsko
Roedy Green - 01 Dec 2005 18:35 GMT
> the system crashes.
You mean has an exception or the JVM crashes?
If the JVM crashes, you need to create the tiniest version of your
program possible that still crashes the system and submit it to Sun.
See http://mindprod.com/jgloss/bugs.html

Signature
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
Edsko de Vries - 05 Dec 2005 09:53 GMT
Ok, I suppose that was sloppy language. I get an exception, but in
system level code (not one entry in the stack trace is from my own
code).
Anyway, I found a way to fix it, which I thought I'd share :-) : I
redefined changeSelection in JTable:
public void changeSelection(int rowIndex, int columnIndex, boolean
toggle, boolean extend)
{
super.changeSelection(rowIndex, columnIndex, toggle, extend);
if(editCellAt(rowIndex, columnIndex))
getEditorComponent().requestFocusInWindow();
}
In other words, as soon as the other clicks on a cell or tabs to a cell
using the keyboard, the cell is immediately put into edit mode and gets
focus. Thus, when the input method is used, the active component
accepts text input and everything is fine.
I first tried to override editCellAt() instead, by doing something like
public boolean editCellAt(int row, int column, EventObject e)
{
boolean r = super.editCellAt(row, column, e);
if(r)
getEditorComponent().requestFocusInWindow();
return r;
}
But that doesn't _quite_ work: when the user types the first character
in a cell, editCellAt gets invoked, and the textfield that is
responsible for editing the cell then receives focus. Unfortunately,
that is only _after_ the first character, so you still get an exception
on the first character.
Edsko