Расширяющий класс KeyListener не реагирует на нажатия клавиш
Извините за то, что это дубликат - я спешил, когда написал это, и у меня не было времени проверить. Хотя я думаю, что это было бы быстрее, теперь, когда я думаю об этом...
Возможный дубликат:
Java KeyListener для JFrame не отвечает?
Я пишу приложение и пытаюсь сделать горячие клавиши. Я решил использовать KeyListener
это все, что я знаю на данный момент. Тем не менее, класс не реагирует на нажатия клавиш. Как бы я исправить эту ошибку? Если есть альтернатива KeyListener
это будет делать то же самое, пожалуйста, дайте мне знать и желательно привести пример того, как это будет работать.
Основной класс
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
import panels.TabBar;
public class __mn implements KeyListener {
static JFrame disp = new JFrame("dat app");
static TabBar tabs = new TabBar();
public static void main(String[] args) {
disp.setLayout(new BorderLayout());
disp.add(tabs, BorderLayout.PAGE_START);
disp.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
disp.setSize(TabBar.PREF_WIDTH, 500);
disp.setResizable(false);
disp.setLocationRelativeTo(null);
disp.addKeyListener(new __mn());
disp.setVisible(true);
}
@Override
public void keyPressed(KeyEvent e) {
System.out.println(e.paramString());
}
//Unused
@Override public void keyReleased(KeyEvent e) {
System.out.println(e.paramString());
}
@Override public void keyTyped(KeyEvent e) {
System.out.println(e.paramString());
}
}
Класс TabBar
package panels;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
//http://www.dreamincode.net/forums/topic/245148-java-key-binding-tutorial-and-demo-program/
public class TabBar extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
public static final int NONE = -1;
public static final int INBOX = 0;
public static final int SEND_MSG = 1;
public static final int PRIVATE_CHAT = 2;
public static final int FEEDBACK = 3;
public static final int PREF_WIDTH = 425;
private static final String[] tabNames = {"Inbox", "Send a message", "Private chat", "Feedback"};
private static final JButton btnInbox = new JButton(tabNames[INBOX]);
private static final JButton btnSendMSG = new JButton(tabNames[SEND_MSG]);
private static final JButton btnPrivChat = new JButton(tabNames[PRIVATE_CHAT]);
private static final JButton btnFeedback = new JButton(tabNames[FEEDBACK]);
public int currentTab = -1;
public TabBar() {
this(new FlowLayout());
}
public TabBar(LayoutManager layout) {
super(layout);
add(btnInbox);
add(btnSendMSG);
add(btnPrivChat);
add(btnFeedback);
btnInbox.addActionListener(this);
btnSendMSG.addActionListener(this);
btnPrivChat.addActionListener(this);
btnFeedback.addActionListener(this);
setBackground(Color.BLACK);
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.paramString());
if (e.getSource() == btnInbox)
currentTab = INBOX;
else if (e.getSource() == btnSendMSG)
currentTab = SEND_MSG;
else if (e.getSource() == btnPrivChat)
currentTab = PRIVATE_CHAT;
else if (e.getSource() == btnFeedback)
currentTab = FEEDBACK;
else currentTab = NONE;
}
public void hotkeyPressed(char pressed) {
pressed = Character.toLowerCase(pressed);
System.out.println("Hotkey pressed: " + pressed);
switch (pressed) {
case 'i':
setTab(INBOX);
break;
case 's':
setTab(SEND_MSG);
break;
case 'p':
setTab(PRIVATE_CHAT);
break;
case 'f':
setTab(FEEDBACK);
break;
default:
break;
}
}
private void setTab(int tab) {
System.out.println("Somthing pressed! tab=" + tab);
currentTab = tab;
switch (tab) {
case INBOX:
btnInbox.requestFocusInWindow();
}
}
}
2 ответа
Как бы я исправить эту ошибку?
Не совсем ошибка, а не несовместимость.
Если есть альтернатива KeyListener, которая будет делать то же самое, пожалуйста, дайте мне знать и предпочтительно приведите пример того, как это будет работать.
Не использовать KeyListener
/KeyAdapter
для компонентов Swing, так как есть проблемы с фокусом, которые можно обойти, позвонив requestFocusInWindow()
на компоненте после его видимости, чтобы убедиться, что он имеет фокус и, конечно, setFoucsable(true);
должен быть вызван, если компонент не фокусируется как JLabel
,
Swing компоненты должны использовать KeyBinding
s, которая преодолевает вышеупомянутые проблемы путем автоматического вызова setFocusable(true)
на компоненте, к которому KeyBinding
добавлено и т. д.
Вот небольшой пример:
void addKeyBinding(JComponent jc) {
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), "A pressed");
jc.getActionMap().put("esc pressed", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
System.out.println("A pressed");
}
});
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), "A released");
jc.getActionMap().put("A released", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
System.out.println("A released");
}
});
}
Вы бы назвали этот метод с экземпляром JComponent
т.е. JPanel
и т.д., что вы хотите добавить Keybinding
тоже:
JPanel p=new JPanel();
addKeyBinding(p);
Другие предложения по коду:
Всегда создавайте компоненты Swing на
Event Dispatch Thread
с помощьюSwingUtilities.invokeXXX
блокНе реализуйте
Listener
лайкActionListener
на самом классе, если этот класс не будет использоваться в качествеListener
только, или вы хотите выставить реализующие классы /Listeners
методы для других классов.
JFrame состоит из множества различных компонентов и, как таковой, не может быть изначально сфокусирован. Без фокуса он не может получать ключевые события. Есть много решений для этого. Я только собираюсь предложить это:
Не отвечает KeyListener для JFrame
И я порекомендую вам Google "Keylistener на jframe Java", чтобы найти больше информации. Как я уже сказал, есть много способов решить эту проблему.