Вопрос

Я пытаюсь реализовать KeyListener для моего JFrame.В конструкторе я использую этот код:

System.out.println("test");
addKeyListener(new KeyListener() {
    public void keyPressed(KeyEvent e) { System.out.println( "tester"); }

    public void keyReleased(KeyEvent e) { System.out.println("2test2"); }

    public void keyTyped(KeyEvent e) { System.out.println("3test3"); }
});

Когда я запускаю его, test на моей консоли появляется сообщение.Однако, когда я нажимаю клавишу, я не получаю никаких других сообщений, как будто KeyListener его там даже не было.

Я подумал, что это может быть из-за того, что основное внимание уделяется не JFrame
и вот они KeyListener не получает никаких событий.Но я почти уверен, что это так.

Есть ли что-то, чего мне не хватает?

Это было полезно?

Решение

Вы должны добавить свой keyListener для каждого компонента, который вам нужен. Только компонент с фокусом будет отправлять эти события. Например, если у вас есть только один TextBox в вашем JFrame, этот TextBox имеет фокус. Поэтому вы также должны добавить KeyListener к этому компоненту.

Процесс такой же:

myComponent.addKeyListener(new KeyListener ...);

Примечание. Некоторые компоненты не могут фокусироваться, например, JLabel.

Чтобы настроить их на фокусировку, вам необходимо:

myComponent.setFocusable(true);

Другие советы

Если вы не хотите регистрировать прослушиватель для каждого компонента,
Вы можете добавить свой собственный KeyEventDispatcher в KeyboardFocusManager :

public class MyFrame extends JFrame {    
    private class MyDispatcher implements KeyEventDispatcher {
        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            if (e.getID() == KeyEvent.KEY_PRESSED) {
                System.out.println("tester");
            } else if (e.getID() == KeyEvent.KEY_RELEASED) {
                System.out.println("2test2");
            } else if (e.getID() == KeyEvent.KEY_TYPED) {
                System.out.println("3test3");
            }
            return false;
        }
    }
    public MyFrame() {
        add(new JTextField());
        System.out.println("test");
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.addKeyEventDispatcher(new MyDispatcher());
    }

    public static void main(String[] args) {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}

InputMaps и ActionMaps были разработаны для захвата ключевых событий для компонента, его и всех его подкомпонентов или всего окна. Это контролируется с помощью параметра в JComponent.getInputMap (). См. Как использовать привязки клавиш для получения документации.

Прелесть этого дизайна в том, что можно выбирать, какие нажатия клавиш важны для мониторинга и запускать различные действия на основе этих нажатий клавиш.

Этот код вызовет dispose () для JFrame, когда клавиша escape будет нажата в любом месте окна. JFrame не является производным от JComponent, поэтому вы должны использовать другой компонент в JFrame для создания привязки ключей. Панель содержимого может быть таким компонентом.

InputMap inputMap; 
ActionMap actionMap;
AbstractAction action;
JComponent component;

inputMap  = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
actionMap = component.getActionMap();

action    = new AbstractAction()
{
   @Override
   public void actionPerformed(ActionEvent e)
   {
      dispose();
   }
};

inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dispose");
actionMap.put("dispose", action);

KeyListener имеет низкий уровень и применяется только к одному компоненту. Несмотря на попытки сделать его более удобным, JFrame создает ряд компонентов, наиболее очевидной из которых является панель содержимого. Интерфейс JComboBox также часто реализуется аналогичным образом.

Стоит отметить, что события мыши работают странным образом, немного отличным от ключевых событий.

Подробнее о том, что вам следует делать, читайте в моем ответе на универсальной клавиатуре приложения ярлык - Java Swing .

У меня была та же проблема, пока я не прочитал, что настоящая проблема связана с FOCUS, поскольку ваш JFrame уже добавил слушателей, но кадр тура никогда не находится на Focus, потому что в вашем JFrame есть много компонентов, которые также являются фокусируемыми, поэтому попробуйте:

JFrame.setFocusable(true);

Удачи

Дейон (и любой другой, кто задает подобный вопрос), вы могли бы использовать код Питера выше, но вместо печати в стандартный вывод вы проверяете код клавиши PRESSED, RELEASED или TYPED.

@Override
public boolean dispatchKeyEvent(KeyEvent e) {
    if (e.getID() == KeyEvent.KEY_PRESSED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    } else if (e.getID() == KeyEvent.KEY_RELEASED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    } else if (e.getID() == KeyEvent.KEY_TYPED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    }
    return false;
}

для захвата ключевых событий ВСЕХ текстовых полей в JFrame , можно использовать ключевой постпроцессор событий. Вот рабочий пример после добавления очевидных включений.

public class KeyListenerF1Demo extends JFrame implements KeyEventPostProcessor {
    public static final long serialVersionUID = 1L;

    public KeyListenerF1Demo() {
        setTitle(getClass().getName());

        // Define two labels and two text fields all in a row.
        setLayout(new FlowLayout());

        JLabel label1 = new JLabel("Text1");
        label1.setName("Label1");
        add(label1);

        JTextField text1 = new JTextField(10);
        text1.setName("Text1");
        add(text1);

        JLabel label2 = new JLabel("Text2");
        label2.setName("Label2");
        add(label2);

        JTextField text2 = new JTextField(10);
        text2.setName("Text2");
        add(text2);

        // Register a key event post processor.
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventPostProcessor(this);
    }

    public static void main(String[] args) {
        JFrame f = new KeyListenerF1Demo();
        f.setName("MyFrame");
        f.pack();
        f.setVisible(true);
    }

    @Override
    public boolean postProcessKeyEvent(KeyEvent ke) {
        // Check for function key F1 pressed.
        if (ke.getID() == KeyEvent.KEY_PRESSED
                && ke.getKeyCode() == KeyEvent.VK_F1) {

            // Get top level ancestor of focused element.
            Component c = ke.getComponent();
            while (null != c.getParent())
                c = c.getParent();

            // Output some help.
            System.out.println("Help for " + c.getName() + "."
                    + ke.getComponent().getName());

            // Tell keyboard focus manager that event has been fully handled.
            return true;
        }

        // Let keyboard focus manager handle the event further.
        return false;
    }
}

Хм .. какой класс ваш конструктор? Возможно какой-то класс, расширяющий JFrame? Конечно, фокус окна должен быть на окне, но я не думаю, что это проблема.

Я расширил ваш код, попытался запустить его, и он сработал - нажатие клавиш привело к выводу на печать. (запускать с Ubuntu через Eclipse):

public class MyFrame extends JFrame {
    public MyFrame() {
        System.out.println("test");
        addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) {
                System.out.println("tester");
            }

            public void keyReleased(KeyEvent e) {
                System.out.println("2test2");
            }

            public void keyTyped(KeyEvent e) {
                System.out.println("3test3");
            }
        });
    }

    public static void main(String[] args) {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}

Это должно помочь

    yourJFrame.setFocusable(true);
    yourJFrame.addKeyListener(new java.awt.event.KeyAdapter() {


        @Override
        public void keyTyped(KeyEvent e) {
            System.out.println("you typed a key");
        }

        @Override
        public void keyPressed(KeyEvent e) {
            System.out.println("you pressed a key");
        }

        @Override
        public void keyReleased(KeyEvent e) {
            System.out.println("you released a key");
        }
    });

У меня была такая же проблема. Я последовал совету Бруно и обнаружил, что добавление KeyListener просто к " first " Кнопка в JFrame (то есть, в левом верхнем углу) сделала свое дело. Но я согласен с вами, это своего рода тревожное решение. Так что я возился и нашел более аккуратный способ исправить это. Просто добавьте строку

myChildOfJFrame.requestFocusInWindow();

к вашему методу main, после того как вы создали свой экземпляр своего подкласса JFrame и сделали его видимым.

лол....все, что вам нужно сделать, это убедиться, что

addKeyListener(это);

правильно помещен в ваш код.

Вы можете настроить собственные JComponents, чтобы их родительский JFrame фокусировался.

Просто добавьте конструктор и передайте JFrame. Затем сделайте вызов setFocusable () в paintComponent.

Таким образом, JFrame всегда будет получать KeyEvents независимо от того, нажаты ли другие компоненты.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top