Ha a JTable cellához egy egyedi, JPanel-re épített CellEditor komponenst rendelek, amely tartalmaz egy szerkeszthető szöveges mezőt is, a billentyűzetet használva nem lesz szerkeszthető a szöveges mező, mert alapesetben a JPanel kapja meg a fókuszt, nem pedig a szöveges mező.

A megoldást Sanhtosh Kumar találta meg és írta le blogjában, az eredeti cikk itt érhető el. Hálás köszönet érte! Ez egy nagyon bonyolult probléma volt.

Út a megoldás felé

Kumar először azt vizsgálta, hogy a DefaultTableCellEditor használata esetén a KeyEvent-ek hogyan kerülnek továbbításra a JTextField objektumnak, és a következő stack trace-t rögzítette:

java.lang.Exception: Stack trace
    at java.lang.Thread.dumpStack(Thread.java:1082)
    at santhosh.CustomEditorDemo$1.insertUpdate(CustomEditorDemo.java:26)
    at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:184)
    at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:749)
    at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:706)
    at javax.swing.text.PlainDocument.insertString(PlainDocument.java:114)
    at javax.swing.text.AbstractDocument.replace(AbstractDocument.java:668)
    at javax.swing.text.JTextComponent.replaceSelection(JTextComponent.java:1072)
    at apple.laf.AquaLookAndFeel$AquaKeyTypedAction.actionPerformed(AquaLookAndFeel.java:1575)
    at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1535)
    at javax.swing.JComponent.processKeyBinding(JComponent.java:2470)
    at javax.swing.JTable.processKeyBinding(JTable.java:3330)
    at javax.swing.JComponent.processKeyBindings(JComponent.java:2516)
    at javax.swing.JComponent.processKeyEvent(JComponent.java:2433)
    at java.awt.Component.processEvent(Component.java:4975)
    at java.awt.Container.processEvent(Container.java:1613)
    at java.awt.Component.dispatchEventImpl(Component.java:3681)
    at java.awt.Container.dispatchEventImpl(Container.java:1671)
    at java.awt.Component.dispatchEvent(Component.java:3543)
    at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1713)

Ami a stack trace-ből kiderült

  1. A felhasználó a kurzorbillentyűkkel a szerkeszteni kívánt cellára navigál.
  2. Ilyenkor a fókusz JTable objektumé, ezért ő kapja a bellentyűeseményeket.
  3. A JTable felülírja a processKeyBinding(...) metódust (lásd a félkövér sort a stack trace-ben)
  4. A felülírt processKeyBinding(...) metódus a következő módon befolyásolja a működést:
    1. Megkérdezi a TableCellEditor-t, hogy a kapott KeyEvent aktiválhatja-e a CellEditor-t.
    2. Ha igen, akkor aktiválja a CellEditor-t és továbbítja a KeyEvent eseményt az aktuális CellEditor komponensnek.

Az ellesett trükk

A lényeg az események továbbításban rejlik. Kumar a következő képpen írta felül a JTable processKeyBinding(...) metódusát:

protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed){
    InputMap map = editorComp.getInputMap(condition);
    ActionMap am = editorComp.getActionMap();

    if(map!=null && am!=null && isEnabled()){
        Object binding = map.get(ks);
        Action action = (binding==null) ? null : am.get(binding);
        if(action!=null){
            return SwingUtilities.notifyAction(action, ks, e, editorComp, e.getModifiers());
        }
    }
    return false;
}

 

A fenti kód megoldotta a problémát: bármely billentyűt leütve a kijelölt táblázatcellába bekerül a begépelt karakter, viszont a cellaszerkesztő még mindig nem kapta meg a fókuszt, ezért még a következő metódust is felülírta:

public void addNotify(){
    super.addNotify();
    editorComp.requestFocus();
}

Kapcsolódó cikkek

Az eredeti cikk

http://jroller.com/santhosh/entry/keyboard_handling_in_tablecelleditor

Kategória: Java

Látogatók

88277
Ma51
Tegnap96
Ezen a héten388
Ebben a hónapban1307
Összesen88277
Statistik created: 2017-11-17T18:59:48+00:00
Bejelentkezett felhasználók 0
Regisztrált felhasználók 1
Ma regisztráltak 0