Search code examples
javaswingjframekey-eventsfocusable

Disable key events


Im making a quiz application, and when a team pushed their buttons (keyboard keys), i want my JFrame to stop listening to other pushes untill the next question or if the answer is wrong.

How can i stop listening to key events? I tried setting the JFrame to non-focusable. I try to do this in the update() function.

Here is my code of the JFrame implementation :

public class QuizView extends JPanel implements View {

    private Observable $model;
    private Controller $controller;     
    private Question $question;


    public QuizView(Observable model, Controller controller){
        setFocusable(true);

        $model = model;

        if (controller == null)
            $controller = new QuizController(model);
        else
            $controller = controller;

        $question = null;   

    }

    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        this.setBackground(Color.WHITE);
        int h, w; /* Width & heigth */
        ArrayList<String> answers = null;
        String answer;
        String progression = ""; /* The progression : e.g. 2/25 , question 2 of 25 */
        int current, total;

        Multipleanswer multipleanswerQuestion;
        Multiplechoice multiplechoiceQuestion;

        /* If the question isn't empty */
        if (!($question == null)) {

            h = getHeight();
            w = getWidth();

            /* Set the font for the question itself */
            g.setFont(new Font("Serif", Font.PLAIN, 65));

            current = ((QuizModel) getModel()).getI() ; /* What question we are at */
            total = ((QuizModel) getModel()).getQuestions().size(); /* If the size of the arraylist is N, there are N + 1 questions */

            progression += current;
            progression += "/";
            progression += total;

            /* Draw the question*/
            g.drawString($question.getQuestion(), 250, 100);

            /* Set a smaller font */
            g.setFont(new Font("Serif", Font.PLAIN, 30));

            /* Draw the progression */
            g.drawString(progression, w - 50, 25);


            /* Set a smaller font for the answers */
            g.setFont(new Font("Serif", Font.PLAIN, 40));

            /* If the type of the question is multipleanswer */
            if ($question.getType() == QuestionType.MULTIPLEANSWER) {

                /* Cast it to multipleanswer question */
                multipleanswerQuestion = (Multipleanswer) $question;

                /* Get the answers */
                answers = multipleanswerQuestion.getAnswers();
            } else if ($question.getType() == QuestionType.MULTIPLECHOICE) {

                /* Cast it to multiplechoice question */
                multiplechoiceQuestion = (Multiplechoice) $question;

                /* Get the answers */
                answers = multiplechoiceQuestion.getAnswers();
            }

            /* Speed questions don't show answers so we only display answers if it's not a speed question */
            if($question.getType() != QuestionType.SPEED){
                /* Draw each answer */
                for (int i = 0; i < answers.size(); i++) {
                    answer = (i + 1) + ") " + answers.get(i);
                    g.drawString(answer, 250, 260 + (100 * i)); /* 300 is spacing from question , 100*i is spacing between answers */
                }
            }

        }
    }

    public void update(Observable arg0, Object arg1) {
        $question = (Question) arg1;

        maximizeFrame(); /* Maximize the frame first */


        /* Add a keylistener for every team */
        addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                int teamSize; /* team size*/
                teamSize = ((QuizModel) getModel()).getTeams().size();
                if (Character.getNumericValue(e.getKeyChar()) <= teamSize) { /* If you pressed a number under the teamsize we listen to it */
                    minimizeFrame(); /* Minimize the frame */

                    /* If this question has a media path we need to pause the audio/video, we also check if the user has installed vlcplayer and selected the right path */
                    if($question.getMediaPath() != null && QuizSoftwareModel.$vlcPath != null)
                        ((QuizController)getController()).pause(); /* Pause the video */

                    /* Give a pop up message to the admin that a team has pushed their button */
                    ((QuizController)getController()).showScoreView(Character.getNumericValue(e.getKeyChar()));
                }

            }
        }); 


        repaint();
    }


    /**
     * Maximize the parent JFrame so the teams can see the question
     */
    protected void maximizeFrame() {
        JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
        topFrame.setState(JFrame.NORMAL);

    }

    /**
     * Minimize the parent JFrame so the teams can't see the question anymore 
     */
    protected void minimizeFrame() {
        JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
        topFrame.setState(JFrame.ICONIFIED);
        topFrame.setFocusable(false); /* Don't make it focusable anymore */

    }

    @Override
    public void setController(Controller controller) {
        $controller = controller;

    }

    @Override
    public Controller getController() {
        return $controller;
    }

    @Override
    public void setModel(Observable model) {
        $model = model;

    }

    @Override
    public Observable getModel() {
        return $model;
    }

    @Override
    public Controller defaultController(Observable model) {
        return new QuizController(model);
    }
}

Solution

  • Use a global variable for this.

    static boolean isPressed = false

    on key press event

     if(!isPressed){
              isPressed = true;
              performYourOperation()
    }    
    
    private void performYourOperation(){
      //DO your stuff
      isPressed = false
    }