Tabulator-Taste in Swing-UI selbst auswerten

Hallo zusammen, hat jemand zufällig schon mal versucht, selbst die Tabulator-Taste auszuwerten? Diese scheint sehr sehr fest an das Durchwechseln der Ui-Elemente gebunden zu sein.

Hintergrund ist, dass ich analog zum „Total Commander“ (oder früher „Norton Commander“) für meinen japanischen Vokabeltrainer einen Listen-Commander zum Bearbeiten von Vokabellisten geschrieben habe. Das fuinktioniert auch alles so weit wie es soll, nur dass ich nicht mit der Tabulator-Taste die aktive Seite wechseln kann. Das liegt im Moment auf F1, ist für meine seit „Ewigkeiten“ eingewöhnten Finger aber extrem unpraktisch.

Ich habe selbst schon danach gegoogelt, allerdings ohne Erfolg bisher.

Anbei ein Bild vom Anwendungszweck:

Kannst du JPanel (Java Platform SE 8 ) s innerhalb der Listen nutzen?

E: Und auch einmal hier weiterlesen How to Use the Focus Subsystem (The Java™ Tutorials > Creating a GUI With Swing > Using Other Swing Features)

Eventuell mittels component.setFocusTraversalKeysEnabled(false) ?

Vielen Dank ihr beiden.

Zur ersten Frage: Natürlich beinhaltet meine Anwendung Panel.

Zum letzten Beitrag: component.setFocusTraversalKeysEnabled(false) hat leider nichts gebracht.

Aber im Link How to Use the Focus Subsystem (The Java™ Tutorials > Creating a GUI With Swing > Using Other Swing Features) aus der zweiten Antwort fand sich die Lösung. Mit der folgenden Methode, der ich das JDialog-Objekt übergebe, kann ich die Tabulator-Taste selbst zuweisen:

/**
 * Löscht in der übergebenen Komponente die normalen Tastenbelegungen (Tabulator und
 * Shift-Tabulator) zum Wechseln durch die Gui-Komponenten, die den Focus bekommen können.
 *
 * Dies wird etwa benötigt, wenn man die Tabulator-Taste in einer Anwendung zu eigenen Zwecken
 * nutzen möchte.
 */
public static void setFocusTraversalKeysToEmptySet(Component component) {
    Set<AWTKeyStroke> forwardKeys = Collections.emptySet();
    Set<AWTKeyStroke> backwardKeys = Collections.emptySet();
    component.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, forwardKeys);
    component.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, backwardKeys);
}

(Vielleicht würde hier auch ein und das selbe Set ausreichen, das habe ich nicht ausprobiert.)

Das Zuweisen der Taste selbst erfolgt bei mir über ein paar Methoden in unterschiedlichen Klassen auf diese Weise:

  1. setKeyBindingTabulator(() -> toOtherSide());

/** Fügt die Tastaturbindung Tabulator hinzu. */
protected void setKeyBindingTabulator(Runnable tabulatorRunnable) {
    BindKeysOnRootPane bind = new BindKeysOnRootPane(getRootPane());
    bind.setKeyBindingTabulator(tabulatorRunnable);
}
/** Fügt die Tastaturbindung Tabulator hinzu. */
public void setKeyBindingTabulator(Runnable tabulatorRunnable) {
    putIntoInputMapWhenInFocusedWindow(KEYSTROKE_TABULATOR, KEYBINDING_TABULATOR);
    putIntoActionMapOfRootPane(KEYBINDING_TABULATOR, runnableToAction(tabulatorRunnable));
}

mit

public static final String KEYBINDING_TABULATOR = "TABULATOR";

public static final int KEYEVENT_TABULATOR = KeyEvent.VK_TAB;

public static final KeyStroke KEYSTROKE_TABULATOR = createUnmodifiedKeystroke(KEYEVENT_TABULATOR);

private static KeyStroke createUnmodifiedKeystroke(int keyevent) {
    return KeyStroke.getKeyStroke(keyevent, 0);
}

Ich hab das hier nur ergänzt, falls später mal jemand über eine Suche auf diesen Beitrag stößt. Dann kann man sich damit den gesamten benötigten Code zum Setzen einer eigenen Belegung für den Tabulator zusammentragen.

1 Like

Ich habe doch nochmal ein kleines, einzeln ausführbares Beispiel geschrieben:

package stc.ui;

import java.awt.AWTKeyStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Collections;
import java.util.Set;

import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class TabulatorKeyUsageDemo {

    private final JFrame frame;

    private final JLabel leftLabel;
    private final JLabel rightLabel;

    private boolean left;

    public TabulatorKeyUsageDemo() {
        frame = new JFrame();
        leftLabel = new JLabel("links");
        rightLabel = new JLabel("rechts");
        createGui();
        left = true;
    }

    private void createGui() {
        init();

        frame.add(leftLabel);
        frame.add(rightLabel);

        tabulatorPressed();
    }

    private void init() {
        initFrame();
        initLabels();
        setFocusTraversalKeysToEmptySet();
        keybindingForTabulator();
    }

    private void initFrame() {
        frame.setTitle("Tabulator-Test");
        frame.setPreferredSize(new Dimension(300, 100));
        frame.setLayout(new GridLayout(1, 0, 2, 2));
    }

    private void initLabels() {
        leftLabel.setHorizontalAlignment(JLabel.CENTER);
        rightLabel.setHorizontalAlignment(JLabel.CENTER);
    }

    private void setFocusTraversalKeysToEmptySet() {
        Set<AWTKeyStroke> forwardKeys = Collections.emptySet();
        Set<AWTKeyStroke> backwardKeys = Collections.emptySet();
        frame.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, forwardKeys);
        frame.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, backwardKeys);
    }

    private void keybindingForTabulator() {
        KeyStroke keyStrokeTabulator = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);

        JComponent rootPane = frame.getRootPane();
        InputMap inputMap = rootPane .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        inputMap.put(keyStrokeTabulator, "tabulator");

        rootPane.getActionMap().put("tabulator", new AbstractAction() {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                tabulatorPressed();
            }
        });
    }

    private void tabulatorPressed() {
        if (left) {
            leftLabel.setForeground(Color.RED);
            rightLabel.setForeground(Color.BLUE);
        }
        else {
            leftLabel.setForeground(Color.BLUE);
            rightLabel.setForeground(Color.RED);
        }
        left = !left;
    }

    public void run() {
        SwingUtilities.invokeLater(() -> {
            frame.pack();
            frame.setVisible(true);
        });
    }

    public static void main(String[] args) {
        new TabulatorKeyUsageDemo().run();
    }

}
1 Like

Ich war mit nicht sicher, ob du nicht vielleicht JavaFX verwendest … sonst hätte meine Antwort zielgerichteter sein können

Und Code gab es ja anfangs auch keinen