您好我正在尝试将KeyListener添加到JFrame。我以前做过这个,这很完美。现在我正在复制代码让它听另一个JFrame,但现在它由于某种原因停止了工作。我不知道自己做错了什么。
编辑:看起来一切正常,直到我从屏幕内的两个JPanel之一按下按钮。它就像之后失去了焦点一样。我该如何解决这个问题?
这是我添加KeyListener的新JFrame的构造函数:
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);
}
}
有人知道什么是错的?非常感谢帮助,因为这是针对学校的项目。
谢谢!
答案 0 :(得分:1)
是啊我现在看到了:)在这种情况下,它需要更多参与,您需要使用应用程序范围的操作,或者应用程序范围的密钥监听器,因为当子组件具有时,KeyListeners将无法处理容器焦点......看到这个问题
Setting up application wide Key Listeners
编辑:确定总是有一个快速而肮脏的修复: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);
}
}
所以基本上你可以为你的组件添加一个焦点监听器..但是对于这个特殊的hack,你需要为你的所有子组件做这个...显然你只需要定义一个{{1}并且你可以在任何地方重复使用它,但通常有一个理由为什么一个组件有焦点所以你不想让它失去焦点..但也许在你的情况下它并不重要。
所以只是为了澄清,如果没有上面JButton上的FocusListener
,“TEST”会在控制台中打印,直到我点击按钮,然后它就不再有效了。然后使用FocusListener
,它始终有效,因为FocusListener
会在按钮具有焦点时重新获得焦点,因此JFrame
上的KeyListener
将再次起作用。
解决此问题的另一种方法是定义KeyAdapter
的一个实例,并将其设置为KeyListener
到该窗口中的所有组件。
答案 1 :(得分:0)
我意识到这个线程有点旧,但在尝试捕获全局级别的击键时我会不断遇到它。我终于想出了一个很好的方法来做到这一点,并想到我会在这里发帖给别人(和我自己,因为我确定我将在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是首选的方法,但有时候你不应该用斧头去除前额上的蚊子。 ; - )