Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java KeyListener仅在单击画布后才处于活动状态_Java_Swing_Canvas_Focus_Keylistener - Fatal编程技术网

Java KeyListener仅在单击画布后才处于活动状态

Java KeyListener仅在单击画布后才处于活动状态,java,swing,canvas,focus,keylistener,Java,Swing,Canvas,Focus,Keylistener,我有一个类实现了KeyListener,一切正常,但有一个小问题,我的KeyListener只有在我点击画布后才能工作,所以如果我开始一个游戏,我必须点击它一次,然后我才能使用我的键盘,代码: public class Game extends Canvas implements Runnable { .... initGame() { ... addKeyListener(new Keyboard()); setFocusable

我有一个类实现了
KeyListener
,一切正常,但有一个小问题,我的
KeyListener
只有在我点击画布后才能工作,所以如果我开始一个游戏,我必须点击它一次,然后我才能使用我的键盘,代码:

public class Game extends Canvas implements Runnable {
    ....
    initGame() {
        ...
        addKeyListener(new Keyboard());
        setFocusable(true);
    }

    private class Keyboard implements KeyListener {
        ...
    }
}

-是否有一种方法可以使我的画布在创建后处于“活动”状态?

KeyListener
仅在注册到的组件可聚焦且具有焦点时才会响应关键事件

虽然您可以使用
requestFocusInWindow
,但不能保证焦点会转移到组件上,如果由于某种原因(您单击另一个组件)丢失了焦点,那么您将返回到原点


更好的解决方案是使用基于
JComoponet
的组件(如
JPanel
),并利用API定义触发关键事件的焦点级别,如果在使
JFrame
可见后添加
Canvas
,则可能会出现问题

召唤

最后在它上面添加所有组件之后

如果我在使
JFrame
可见后添加
Canvas
,并且我必须单击
Canvas
以获得对它的关注,我就会发生这种情况


--编辑--

示例代码以理解它(请在取消对最后一帧的注释后重试。setVisible(true))


我用下一种方法解决了这个问题:我创建了Canvas对象,向其添加了KeyListener,并使该对象可聚焦。在这些操作之后,我将Canvas对象添加到JFrame中,一切都开始正常工作。

这是因为它没有焦点。对于Swing,通常在基于AWT的较低级别上使用键绑定,
KeyListener
。有关如何使用它们的详细信息,请参阅。此外,Swing中的渲染通常在
JPanel
中进行,而不是在
画布上进行。通过调用
setFocusable(true)设置焦点。@Braj不,该方法只是将组件设置为可聚焦。您正在描述
requestFocusInWindow()
@Braj从描述问题(和示例代码)开始,组件已经可以聚焦,因为OP可以单击组件并激活密钥侦听器……如果您按照@andrewhompson的建议使用密钥绑定,您可以绕过大部分
keystener
的问题。这是我本周第一百次就创建键绑定给出一个简短的回答。根据提供的信息,如果组件是在框架可见后添加的,OP将无法单击框架并查看键事件,以便发生这种情况,画布必须可在屏幕上显示…添加
setBackground(颜色:红色)进入构造函数,您会注意到当框架出现在屏幕上时,
画布
是可见的。调用
setresizeable
可能会使容器无效。Oh和
setSize
将无效,因为框架正在使用其自己的布局管理器,因此当调用容器进行布局时,设置将被丢弃。我在删除
setResizeable
后尝试过。现在显示的帧没有任何高度和宽度。我把它展开,然后按一下键。但它仍然不起作用。一旦我点击框架。关键听众开始工作。按照我的第一个建议。设置
画布
对象的背景色。一旦你调整了框架的大小,框架就会失效,
Canvas
就会显示出来,并对事件做出响应——这就是我的观点。根据OP的说法,他们调用setVisible的时间与问题无关。
frame.setVisible(true)
import java.awt.Canvas;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class CanvasDemo extends Canvas implements ActionListener, KeyListener {

    public CanvasDemo() {
        addKeyListener(this);
        setFocusable(true);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setVisible(true);

        CanvasDemo apple = new CanvasDemo();            
        frame.add(apple);

        frame.setTitle("The Game");
        // frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

    @Override
    // animates rectangle
    public void actionPerformed(ActionEvent arg0) {
        System.out.println("action performed");
    }

    @Override
    public void keyPressed(KeyEvent arg0) {
        System.out.println("key pressed");
    }

    @Override
    public void keyReleased(KeyEvent arg0) {
        System.out.println("key released");
    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        System.out.println("key typed");
    }
}