JFrame没有响应keylistener

时间:2014-06-04 10:38:50

标签: java swing jframe keylistener setfocus

您好我正在尝试将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);
}
}

有人知道什么是错的?非常感谢帮助,因为这是针对学校的项目。

谢谢!

2 个答案:

答案 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是首选的方法,但有时候你不应该用斧头去除前额上的蚊子。 ; - )