Bick
Bick

Reputation: 18521

JPanel keylistener

I am trying to add a key listener that holds a JTabbedPane.
It should switch the tabs when ctrl + tab is received.
But the keypressed event is never sent I tried adding it to the panel and to the tabbed object - but with no success.

Here is my code

SwitchTabsListener ctrlTabListener = new SwitchTabsListener(genericTabbedPanel);  
jMainFrame.addKeyListener(ctrlTabListener);  
genericTabbedPanel.addKeyListener(ctrlTabListener);  

Upvotes: 9

Views: 11633

Answers (4)

Riduidel
Riduidel

Reputation: 22292

In a typical fashion, your key event is not intercepted by the correct Swing component. You have to understand that the first component below the cursor will receive the keyboard event. Were you to select a button with your keyboard, it would be this JButton that would receive the key event.

To make sure you get all those events, you don't have to register on components, but rather by using a KeyboardFocusManager, which will receive key events wherever they occur.

Your code then require the following elements

KeyEventDispatcher myKeyEventDispatcher = new DefaultFocusManager();
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(myKeyEventDispatcher);

myKeyEventDispatcher will then receive calls to dispatchKeyEvent whenever a key is pressed, wherever it is in UI. This way, you can make sure your code is correctly called.

The alternative method of registering key listener would require you to use a HierarchyListener in order for your key listener to be added:removed to each and every swing component that appear to be added/removed as a child of your root component. This is not only cumbersome to write, but also really hard to debug and understand.

This is why I prefer the more brute-force, but although quite elegant way of adding application global key listener to a specific keyboard focus manager.

Upvotes: 15

David Winiecki
David Winiecki

Reputation: 4203

Building from Riduidel's answer, here's a full example. I'm not sure how to determine if the event is from a key press or key release though.

import java.awt.KeyboardFocusManager;
import java.awt.KeyEventDispatcher;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;

public class Exit {
    public static void main(String[] args) {
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new ExitKeyEventDispatcher());
        JFrame frame = new JFrame();
        frame.setBounds(50, 50, 200, 200);
        frame.setVisible(true);
    }
}
class ExitKeyEventDispatcher implements KeyEventDispatcher {
    public boolean dispatchKeyEvent(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
            System.exit(0);
            e.consume();
        }
        return false;
    }
}

Upvotes: 1

dogbane
dogbane

Reputation: 274532

Ctrl+Tab and Ctrl+Shift+Tab allow you to cycle through tabs by default in the Windows LookAndFeel:

UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");

Upvotes: 3

AlexR
AlexR

Reputation: 115328

This should work. This probably does not work for you because

  1. You do not select the correct window.
  2. other component catches this event.

Here is the code I wrote for you.

public class Test {

    public static void main(String[] args) throws InterruptedException {
        JFrame f = new JFrame("aaaa");
        f.setSize(100, 100);
        f.setLocation(100, 100);
        JPanel p = new JPanel();
        f.add(p);

        f.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                System.out.println("pressed");
            }
        });

        p.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                System.out.println("pressed");
            }
        });
        f.setVisible(true);

    }

It works fine. Try to play with it and understand what is the difference between yours and my code. If you fail please send us larger snippet of your code.

Upvotes: 2

Related Questions