JFrame не отвечает на кейлист

1

Привет, я пытаюсь добавить 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);
}
}

Кто-то знает, что случилось? Помощь будет очень признательна, поскольку это проект для школы.

Благодарю!

  • 0
    здесь работает нормально, при условии, что вы сделали JFrame видимым, в консоли появляется «TEST», когда я набираю клавиши.
  • 0
    Вы попробовали первый JFrame правильно? Хм, позвольте мне проверить это снова.
Показать ещё 2 комментария
Теги:
swing
jframe
keylistener
setfocus

2 ответа

1
Лучший ответ

ага, да, я вижу сейчас :) В этом случае это немного более важно, вам нужно использовать действия с широким спектром приложений или хорошо прослушивать ключевые слова приложения, поскольку 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 для всех ваших компонентов в этом окне.

  • 0
    Разве нет быстрого решения, чтобы восстановить фокус на родительском JFrame? Или это не сработает?
  • 0
    Спасибо за помощь; D, но проблема в том, что администратор викторины должен иметь возможность задать новый вопрос -> фокус переходит к JFrame, где задается новый вопрос, но команды по-прежнему должны быть в состоянии нажать свою кнопку в течение этого времени (слушатель находится внутри родительского JFrame), вы понимаете, о чем я? Мне нравится твое грязное исправление, но это все еще не решает эту проблему. Есть ли способ, как родительский JFrame может реагировать на нажатия клавиш? Или я должен добавить вопрос JFrame в JPanel внутри этого JFrame, чтобы решить проблему?
Показать ещё 8 комментариев
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 являются предпочтительным методом, но иногда вам не следует использовать топор для удаления москита со своего лба. ;-)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню