为什么这个keyListener不起作用?

时间:2015-10-16 02:17:48

标签: java events applet

public class game extends Applet implements KeyListener {
int movex = 10;
int movey = 10;
int x = 50, y = 50;
JTextArea typingArea;
Random rand = new Random();
public void paint(Graphics page){
        typingArea = new JTextArea();
        typingArea.addKeyListener(this);

        //Drawing borders w/ Random colors
        page.setColor(new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
        page.drawRect(0,0,200,200);

        //delay
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
        }

        //Draws square          
        page.drawRect(x, y, 10, 10);
        x+=movex;
        y+=movey;

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }
        Dimension d = getSize();
        page.setColor(Color.WHITE);
        page.fillRect(0, 0, d.width, d.height);
        paint(page);
    }

public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();
    System.out.println("Key is pressed");
    switch( keyCode ) { 
        case KeyEvent.VK_UP:
            movex = 0;
            movey = 10;
            break;
        case KeyEvent.VK_DOWN:
            movex = 0;
            movey = -10;
            break;
        case KeyEvent.VK_LEFT:
            movex = -10;
            movey = 0;
            break;
        case KeyEvent.VK_RIGHT :
            movex = 10;
            movey = 0;
            break;
     }
}
@Override
public void keyReleased(KeyEvent arg0) {

}
@Override
public void keyTyped(KeyEvent e) {

}}

目前我正在制作一个快速的蛇游戏作为编程实践,因为我对Java相对较新,但不是编程。使用Applet我正在绘制一个正方形,并通过递增x,y坐标然后以递归方式调用paint方法将其移动。我使用了错误的对象(JTextArea)还是我的方法存在问题。请快点回答,谢谢。

1 个答案:

答案 0 :(得分:0)

让我们看看我们是否可以稍微分解一下......

paint方法中,您创建了JTextArea的新实例,并将自己添加为KeyListener

public void paint(Graphics page) {
    typingArea = new JTextArea();
    typingArea.addKeyListener(this);

这里有三个问题......

  1. 您真的不应该在paint方法中创建新组件。当需要重新绘制组件时(并且可以快速连续调用),paint方法将被调用,paint应该只绘制组件的当前状态,永远不要更改它
  2. 你真的不应该使用带有文本组件的KeyListener
  3. 您实际上从未将JTextArea添加到显示的组件中,这意味着它永远无法获得键盘焦点,因此永远不会触发KeyEvent s
  4. 然后你打电话......

        //delay
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
        }
        //...
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }
    

    在您的paint方法中。这是一个非常糟糕的主意,绘画应该尽可能快地发生,因为直到paint方法存在,Graphics上下文的内容可能不会被绘制到屏幕上

    最后,你打电话给...

        paint(page);
    }
    

    这是一个糟糕的主意,因为一旦调用paint方法,您将永远不会退出StackOverflowException方法(请参阅上一条评论),最终会得到paint

    AWT会在您希望重新绘制组件时调用repaint方法。您可以通过调用KeyListener来请求更新,但是您应该知道,当重绘管理器决定需要更新某些内容时,将会发生绘画,因此可能不会立即发生。

    • 我首先看看Painting in AWT and SwingPerforming Custom Painting,了解绘画是如何运作的。
    • 然后我放弃applet / AWT API并使用Swing或JavaFX,你会得到更好的一般支持。
    • 如果您想使用Swing,我可以查看How to use Swing Timers有关如何生成游戏循环的一些想法
    • 如果您要使用Swing,我建议您查看How to Use Key Bindings并忘记<h:form> <h:dataTable value="#{hsinfo.tableContent}" var="o" styleClass="table" headerClass="table-header" rowClasses="table-odd-row,table-even-row"> <h:column> <f:facet name="header">SBD</f:facet> <h:outputText value="#{o.sbd}"></h:outputText> </h:column> <h:column> <f:facet name="header">Họ Tên</f:facet> <h:outputText value = "#{o.ten}"></h:outputText> </h:column> <h:column> <f:facet name="header">Ngày Sinh</f:facet> <h:outputText value = "#{o.ngaysinh}"></h:outputText> </h:column> <h:column> <f:facet name="header">Giới Tính</f:facet> <h:outputText value = "#{o.gioitinh}"></h:outputText> </h:column> </h:dataTable> </h:form>
    • 你可以看看这个example的一些想法。