【问题标题】:JFrame not responding to keylistenerJFrame没有响应keylistener
【发布时间】:2014-06-04 10:38:49
【问题描述】:

您好,我正在尝试将 KeyListener 添加到 JFrame。我以前做过,而且效果很好。现在我正在复制代码让它监听另一个 JFrame,但现在它由于某种原因停止工作。我不知道我做错了什么。

编辑:看起来一切正常,直到我从屏幕内的 2 个 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);
}
}

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

谢谢!

【问题讨论】:

  • 在这里工作正常,假设你让你的 JFrame 可见,“TEST”会在我键入键时出现在控制台中。
  • 你尝试过第一个 JFrame 对吗?嗯,让我再检查一次。
  • 现在可以了,我们在另一个类中使用了 setVisible 函数,我们现在把它放在构造函数中,现在可以正常工作了。谢谢
  • @Shikamu 还是不行,请检查问题中的EDIT。

标签: java swing jframe keylistener setfocus


【解决方案1】:

啊,是的,我现在看到了 :) 在这种情况下,它涉及的更多一点,您需要使用应用程序范围的操作,或者应用程序范围的键侦听器,因为当子组件具有重点...看到这个问题

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);

    }
}

所以本质上你可以为你的组件添加一个焦点监听器..但是对于这个特定的黑客你需要为你的所有子组件做这件事......显然你只需要定义一个 FocusListener 和您可以在任何地方重用它,但通常组件具有焦点是有原因的,因此您不想让它失去焦点..但在您的情况下可能没关系。

只是为了澄清一下,如果没有上面 JButton 上的 FocusListener,“TEST”会打印在控制台中,直到我单击该按钮,然后它不再起作用。然后使用FocusListener,它将始终有效,因为当按钮获得焦点时,JFrame 将重新获得焦点,因此其上的KeyListener 将再次有效。

解决此问题的另一种方法是定义KeyAdapter 的一个实例,并将其设置为KeyListener 用于该窗口中的所有组件。

【讨论】:

  • 没有快速修复来重新获得对父 JFrame 的关注吗?或者这不起作用?
  • 感谢您的帮助 ;D,但问题是测验的管理员应该能够提出新问题 -> 焦点转到提出新问题的 JFrame,但团队在那段时间里应该仍然可以按下他们的按钮(监听器在父 JFrame 内),你明白我的意思吗?我喜欢你的肮脏修复,但这仍然不能真正解决这个问题。是否有某种方式父 JFrame 仍然可以响应被按下的键?或者我应该在这个 JFrame 中将添加问题 JFrame 设置为 JPanel 来解决问题?
  • 既然这是模型视图控制器,是否有一个选项我可以在更新的 JFrame 中获取焦点?这样也能解决问题。 :)
  • 所以有可能在父 JFrame 内的 JFrame 内输入 JTextField 并且仍然像 F1 一样响应按下的键并在父 JFrame 中处理它们?
  • 使用 JPanel 并将您的组件放入其中并不能解决我担心的问题。如果您对捕获特定键感兴趣,我建议您查看我在回答中链接的问题。
【解决方案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 是首选方法,但有时您不应该使用斧头从额头上清除蚊子。 ;-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 1970-01-01
    相关资源
    最近更新 更多