Как получить фокус для нажатия клавиши в CardLayout?

У меня был пример CardLayout, правильно работающий с кнопкой, а затем я попытался преобразовать его для работы с нажатием клавиши. Я думаю, проблема в том, что у меня нет фокуса, но я не могу успешно установить фокус на кадр или панель. Спасибо!

Я попробовал requestFocusInWindow из фрейма и из первой показанной панели, и это не помогло. Я спросил frame.getFocusOwner(), и он вернул ноль. Я думал, что CardLayout автоматически переместит фокус на верхний элемент, но пока это работало, когда у меня была кнопка, сейчас это не работает.

public class MyCardLayoutExample3 {

    public static void main(String[] args){
    MyCardLayoutExample3 game = new MyCardLayoutExample3();
    game.display();
    }

    void display() {

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setSize(300, 200);

    CardLayout cardLayout = new CardLayout();
    frame.getContentPane().setLayout(cardLayout);

    MyGamePanel3 mgp3 = new MyGamePanel3("minigame A", Color.red);
    frame.getContentPane().add(mgp3);
    frame.getContentPane().add(new MyGamePanel3("minigame B", Color.green));
    frame.getContentPane().add(new MyGamePanel3("minigame C", Color.blue));

    frame.setVisible(true);

    System.out.println("owner: " + frame.getFocusOwner()); //this prints null
    }
}
class MyGamePanel3 extends JPanel implements KeyListener{

    MyGamePanel3(String text, Color bg){

        JLabel textLabel = new JLabel(text);
        this.setBackground(bg);
        this.add(textLabel);
    }

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) {
    System.out.println("keyPressed worked");
    }

    @Override
    public void keyReleased(KeyEvent e) {}
}

person boatswain    schedule 01.05.2019    source источник
comment
Я не вижу вызова метода addKeyListener() в опубликованном вами коде. Вам нужно зарегистрировать переменную mgp3 в качестве прослушивателя ключей для какого-либо компонента в вашем графическом интерфейсе. В качестве альтернативы, возможно, для вашей ситуации подходит привязки клавиш.   -  person Abra    schedule 02.05.2019
comment
I thought that CardLayout would give the focus to the top element automatically, - согласен, но, к сожалению, нет. Проверьте: stackoverflow.com/questions/ 39680714/ для решения   -  person camickr    schedule 02.05.2019
comment
Спасибо @ken за редактирование, я постепенно осваиваюсь.   -  person boatswain    schedule 04.05.2019


Ответы (1)


Изменение привязки клавиш упростило работу примера, спасибо Abra. У меня никогда не работал keyListener, несмотря на то, что я пробовал ссылки выше и многие другие ссылки.

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;

class MyGamePanel extends JPanel{

     MyGamePanel(ActionListener alNext, String text, Color bg){
        JButton buttonNext = new JButton("next");
        buttonNext.addActionListener(alNext);

        JLabel textLabel = new JLabel(text);

        this.setBackground(bg);
        this.add(textLabel);
        this.add(buttonNext);
    }
}
public class MyCardLayoutKeyBindingExample {

        public static void main(String[] args){
           MyCardLayoutKeyBindingExample game = new MyCardLayoutKeyBindingExample();
           game.display();
        }

        void display() {

            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            frame.setLocationRelativeTo(null);
            frame.setSize(300, 200);

            CardLayout cardLayout = new CardLayout();
            //frame.getContentPane().setLayout(cardLayout);
            JPanel mainPanel = new JPanel(cardLayout);
            frame.add(mainPanel);

            ActionListener al1 = e -> cardLayout.next(mainPanel);
            mainPanel.add(new MyGamePanel(al1, "minigame A", Color.red));
            mainPanel.add(new MyGamePanel(al1, "minigame B", Color.green));
            mainPanel.add(new MyGamePanel(al1, "minigame C", Color.blue));


            mainPanel.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "space");
            Action kp = new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    System.out.println("key pressed");
                    }
            };
            mainPanel.getActionMap().put("space", kp);


            frame.setVisible(true);
        }
}
person boatswain    schedule 03.05.2019