java - 如何将焦点切换到 Canvas ?

标签 java swing focus

我有这个类,我想在调用它后立即将焦点切换到 Game 类。我可能不明白焦点的目的,但当我按下开始时,我必须单击游戏 Canvas 本身,以便我可以使用键盘。换句话说:我怎样才能做到这样我就不必点击它来使用键盘?

package com.runner.panels;

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

import javax.swing.JButton;
import javax.swing.JPanel;

import com.runner.main.Game;
import com.runner.main.Main;

public class PlayPanel extends JPanel{

    private static final long serialVersionUID = 1L;

    public PlayPanel(){
        //setting the layout of the playpanel to null
        setLayout(null);

        //setting up the info panel : high score, meters ran, pause button etc...
        JPanel info = new JPanel();
        info.setBounds(0,0,1200,50);
        add(info);

        //back button
        JButton back = new JButton("Back");
        info.add(back);

        Game game = new Game();
        game.setBounds(0,50,1200,521);
        game.setBackground(Color.black);
        add(game);

        back.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                CardLayout cl = (CardLayout) Main.mainp.getLayout();
                cl.show(Main.mainp, "Menu");
            }
        });
    }
}

最佳答案

偏离主题:(有点)

事实上,您正在执行 Main.mainp.getLayout();,静态调用面板告诉我您的设计很差,应该考虑其他选项,例如 Model-view-controller pattern ,一个Observer pattern ,或者至少将 Main 的引用传递给面板,而不是使用静态对象/调用。

回到主题

听起来像是一个常见的 KeyListener 问题。通常要获得焦点,您可以调用 requestFocusInWindow()。但您仍然需要担心其他组件会在事后窃取焦点。

我建议使用 Key Bindings而不是 KeyListener。您可以更好地控制焦点。例如,通过使用

InputMap im = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke("SPACE"), "hitSpace");
panel.getActionMap().put("hitSpace", new AbstractAction(){
    public void actionPerformed(ActionEvent e) {
        // do something.
    }
});

一旦您从 CardLayout 显示操作,面板将立即访问该操作。如果您碰巧使用任何其他会夺走面板焦点的组件,由于 WHEN_IN_FOCUSED_WINDOW 输入映射

,该操作仍然可以访问

这是一个简单的例子。如果它位于面板 A 上,则键入 A,您将看到它被打印出来。如果您键入 B,则不会打印,因为面板 A 在窗口中。此外,如果您尝试按下面板中的按钮来窃取焦点,您仍然可以打字并且仍然可以打印。面板 B 也是如此

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class Main {

    CardLayout layout = new CardLayout();
    JPanel panel = new JPanel(layout);
    JPanel p1 = new JPanel() {
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 300);
        }
    };
    JPanel p2 = new JPanel() {
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 300);
        }
    };
    JButton b1 = new JButton("panelA");
    JButton b2 = new JButton("panelB");

    public Main() {
        addKeyBind(p1, "pressA", "A");
        addKeyBind(p2, "pressB", "B");
        p1.add(new JButton("Button for Panel A"));
        p2.add(new JButton("Button for Panel B"));

        panel.add(p1, "panelA");
        panel.add(p2, "panelB");

        b1.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                show("panelA");
            }
        });
        b2.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                show("panelB");
            }
        });
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(b1);
        buttonPanel.add(b2);

        JFrame frame = new JFrame();
        frame.add(panel);
        frame.add(buttonPanel, BorderLayout.PAGE_END);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public void show(String panelName) {
        layout.show(panel, panelName);
    }

    private void addKeyBind(JComponent comp, String name, final String stroke) {
        InputMap im = comp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        im.put(KeyStroke.getKeyStroke(stroke), name);
        comp.getActionMap().put(name, new AbstractAction(){
            public void actionPerformed(ActionEvent e) {
                System.out.println(stroke + " pressed");
            }
        });
    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                new Main();
            }
        });
    }
}

请花一些时间查看我为您提供的按键绑定(bind)链接,以了解更多信息。

偏离主题

看看@AndrewThompson 关于空布局的评论。学习how to use the LayoutManagers

关于java - 如何将焦点切换到 Canvas ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25227045/

相关文章:

java - 如何在运行 Junit 测试用例时创建用户 session

java - Eclipse:移动 Maven 依赖项

java - 预期与 VariableDeclaratorId 有关的 MouseListener 错误

java - 按钮不创建 JPanel

java - 后续运行程序时如何保存和重新加载JTree?

java - 如何通过使用Maven导入另一个包类?

java - 在 Servlet 中按下了哪个动态创建的按钮

java - 不在 Top Java 上保持专注

android - 更改列表项选择的 View 属性

jquery - 将焦点放在 div contenteditable 元素上