Привет, я пытаюсь добавить KeyListener в JFrame. Я сделал это раньше, и это сработало отлично. Теперь я копирую код, чтобы он прослушивал другой JFrame, но теперь он почему-то перестает работать. Я не знаю, что я сделал неправильно.
EDIT: Похоже, все работает, пока я не нажму кнопку из одной из двух JPanels внутри экрана. После этого он потерял фокус. Как я могу это исправить?
Это конструктор нового JFrame, где я добавляю KeyListener:
public class QuizSoftwareView extends JFrame implements View{
private Observable $model;
private Controller $controller;
public EditQuestionsView $editQuestionsView;
public EditTeamsView $editTeamsView;
public AdministratorMenu $adminMenu;
private boolean $isPressed; /* To check if we already listened to a key press event */
/**
* Constructor to make a new quiz
*/
public QuizSoftwareView(Observable model, Controller controller) {
this.setTitle(QuizSoftwareModel.$language.getMessages().getString("title"));
$model = model;
if (controller == null)
$controller = new QuizSoftwareController(model);
else
$controller = controller;
$isPressed = false;
initComponents();
setFocusable(true);
/* Add a keylistener for every team */
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
System.out.println("TEST");
int teamSize; /* team size*/
teamSize = ((QuizSoftwareModel) getModel()).getQuiz().getModel().getTeams().size();
System.out.println(teamSize);
/* F1 is keycode 112, so % 111 gives 1 -> team 1, team 1 gets button F1, team 2 gets button F2 and so on... */
if((e.getKeyCode() % 111) <= teamSize /*&& !alreadyPressed((e.getKeyCode() % 111))*/) { /* If you pressed a number under the teamsize we listen to it, and that team hasn't pressed their button before */
/* Give a pop up message to the admin that a team has pushed their button */
//buttonPressed((e.getKeyCode() % 111));
System.out.println("TESTT");
((QuizSoftwareController)getController()).showScoreView((e.getKeyCode() % 111));
}
}
});
$isPressed = false;
}
}
Это код, где я делал это раньше (отлично работает):
public class QuizView extends JFrame implements View {
private Observable $model;
private Controller $controller;
private QuestionView $questionView;
private MediaPlayer $mediaView;
private Question $question;
private boolean $isPressed; /* To check if we already listened to a key press event */
public QuizView(Observable model, Controller controller){
setFocusable(true);
$model = model;
if (controller == null)
$controller = new QuizController(model);
else
$controller = controller;
$question = null;
$isPressed = false;
$questionView = new QuestionView($model, null); /* null -> Give the default controller as parameter */
$mediaView = new MediaPlayer($model, null); /* null -> Use default controller */
$model.addObserver($questionView);
$model.addObserver($mediaView);
setTitle("Quiz"); /* Universal word so no messagebundle */
getContentPane().setLayout(new BorderLayout());
getContentPane().add($questionView, BorderLayout.CENTER);
getContentPane().add($mediaView, BorderLayout.EAST);
setExtendedState(this.MAXIMIZED_BOTH);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
((QuizController)getController()).stop();
dispose();
}
});
setFocusable(true);
/* Add a keylistener for every team */
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int teamSize; /* team size*/
teamSize = ((QuizModel) getModel()).getTeams().size();
/* F1 is keycode 112, so % 111 gives 1 -> team 1, team 1 gets button F1, team 2 gets button F2 and so on... */
if((e.getKeyCode() % 111) <= teamSize && !alreadyPressed((e.getKeyCode() % 111))) { /* If you pressed a number under the teamsize we listen to it, and that team hasn't pressed their button before */
/* Give a pop up message to the admin that a team has pushed their button */
buttonPressed((e.getKeyCode() % 111));
((QuizController)getController()).showScoreView((e.getKeyCode() % 111));
}
}
});
$isPressed = false;
pack();
setVisible(false);
}
}
Кто-то знает, что случилось? Помощь будет очень признательна, поскольку это проект для школы.
Благодарю!
ага, да, я вижу сейчас :) В этом случае это немного более важно, вам нужно использовать действия с широким спектром приложений или хорошо прослушивать ключевые слова приложения, поскольку KeyListeners не будут работать с контейнерами, когда дочерний компонент имеет фокус. См. Этот вопрос
Настройка широковещательных приложений Key Listeners
edit: обязательно всегда быстрое и грязное исправление: p
попробуй это:
public class Test2 extends JFrame {
private boolean $isPressed; /*
* To check if we already listened to a key
* press event
*/
/**
* Constructor to make a new quiz
*/
public Test2() {
this.setTitle("");
$isPressed = false;
setFocusable(true);
getContentPane().setLayout(new BorderLayout());
JButton b = new JButton();
b.addFocusListener(new FocusListener() {
@Override
public void focusLost(FocusEvent e) {
// TODO Auto-generated method stub
}
@Override
public void focusGained(FocusEvent e) {
Test2.this.requestFocus();
}
});
getContentPane().add(b);
/* Add a keylistener for every team */
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
System.out.println("TEST");
}
});
$isPressed = false;
b.grabFocus();
pack();
}
/**
* @param args
*/
public static void main(String[] args) {
new Test2().setVisible(true);
}
}
так что по существу вы можете добавить слушателя фокуса к своим компонентам.. но тогда для этого конкретного взлома вам нужно будет сделать это для всех ваших дочерних компонентов... очевидно, вам нужно будет только определить один FocusListener
и вы можете его повторно использовать повсюду, но обычно есть причина, почему компонент сосредоточен, поэтому вы не хотите просто потерять фокус. Но, возможно, в вашем случае это не имеет значения.
поэтому просто уточнить, без FocusListener
на JButton выше, "TEST" печатается на консоли, пока я не FocusListener
кнопку, тогда он больше не работает. Затем с FocusListener
он всегда будет работать, потому что JFrame
вернет фокус, когда кнопка имеет фокус, поэтому KeyListener
на нем снова будет работать.
Другой способ решить эту проблему - определить один экземпляр KeyAdapter
и установить его как KeyListener
для всех ваших компонентов в этом окне.
Я понимаю, что эта ветка немного устарела, но я все время сталкиваюсь с ней, пытаясь захватить нажатия клавиш на глобальном уровне. Я, наконец, понял, как это сделать, и решил, что отправлю сюда других (и я сам, потому что я уверен, что забуду 2 дня).
KeyboardFocusManager kbfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
kbfm.addKeyEventDispather( new KeyEventDispatcher(){
public boolean dispatchKeyEvent(KeyEvent e){
if(e.getID() == KeyEvent.KeyPressed) {
switch(e.getKeyCode()) {
case KeyEvent.VK_A:
//Stuff to do when A is pressed
System.out.println("You pressed the 'A' key");
case KeyEvent.VK_B:
//Stuff to do when B is pressed
System.out.println("You pressed the 'B' key");
// add other cases as needed for other keys
}
}
//Allow event to be redispatched
return false;
}
} );
Я понимаю, что keyBindings являются предпочтительным методом, но иногда вам не следует использовать топор для удаления москита со своего лба. ;-)