【问题标题】:Make graphics move on key events使图形在关键事件上移动
【发布时间】:2016-09-18 04:15:39
【问题描述】:

我正在尝试制作一个能够在按下“i、j、k、l”键(作为箭头键)时移动并在松开时停止的圆圈。尝试创建一个计时器,以便在再次移动之前等待一秒钟,因此动画效果可观,但由于我创建了“while(!quit)”循环,因此没有图形移动或显示。请指出我的错误好吗?

代码:

import java.awt.*;
import java.awt.Color.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Timer;
import java.util.TimerTask;


public class Event_test{
    public static void main(String args[])
    {
        boolean quit = false;

        JFrame Window = new JFrame("Event_test");
        MyCanvas WCanvas = new MyCanvas();
        KeyCatcher k = new KeyCatcher();

        WCanvas.addKeyListener(k);


        Window.getContentPane().add(WCanvas);
        Window.setSize(640, 360);
        Window.setVisible(true);
        Window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        new Notification(1);

        while(!quit)
        {
            WCanvas.update(WCanvas.getGraphics());

            if(!Notification.flag)
            {
                continue;
            }
            else
            {
                Notification.flag = false;
                System.out.println("tic");
                /*
                CONTROLS:
                */

                if(KeyCatcher.KEYS[0])
                {
                    MyCanvas.x--;
                }
                if(KeyCatcher.KEYS[1])
                {
                    MyCanvas.y++;
                }
                if(KeyCatcher.KEYS[2])
                {
                    MyCanvas.x++;
                }
                if(KeyCatcher.KEYS[3])
                {
                    MyCanvas.y--;
                }
                if(KeyCatcher.KEYS[4])
                {
                    quit = true;
                }

                new Notification(1);
            }


        }
    }
}

class MyCanvas extends Canvas
{
    static int x, y;

    public void paint(Graphics g)
    {
        g = this.getGraphics();
        MyClass.drawSomething(g, x, y);
    }
}

class MyClass
{

    public static void drawSomething(Graphics g, int x, int y)
    {
        g.setColor(Color.RED);
        g.drawOval(x, y, 10, 10);
    }
}

class KeyCatcher implements KeyListener
{

    static boolean KEYS[] = new boolean[5];


    public void keyPressed(KeyEvent e)
    {
        if(e.getKeyChar() == 'j'/*IZQ*/)
        {
            KEYS[0] = true;
        }

        if(e.getKeyChar() == 'i'/*ARR*/)
        {
            KEYS[1] = true;
        }

        if(e.getKeyChar() == 'l'/*DER*/)
        {
            KEYS[2] = true;
        }

        if(e.getKeyChar() == 'k'/*ABA*/)
        {
            KEYS[3] = true;
        }

        if(e.getKeyChar() == 'q'/*QUIT*/)
        {
            KEYS[4] = true;
        }
    }

    public void keyReleased(KeyEvent e)
    {
        if(e.getKeyChar() == 'j'/*IZQ*/)
        {
            KEYS[0] = false;
        }

        if(e.getKeyChar() == 'i'/*ARR*/)
        {
            KEYS[1] = false;
        }

        if(e.getKeyChar() == 'l'/*DER*/)
        {
            KEYS[2] = false;
        }

        if(e.getKeyChar() == 'k'/*ABA*/)
        {
            KEYS[3] = false;
        }

        if(e.getKeyChar() == 'q'/*QUIT*/)
        {
            KEYS[4] = false;
        }
    }

    public void keyTyped(KeyEvent e){

    }
}

class Notification{
    static boolean flag = false;
    Timer timer;

    Notification(int seconds)
    {
        timer = new Timer();
        timer.schedule(new Task(), seconds*1000);
    }

    class Task extends TimerTask
    {
        public void run()
        {
            //What task does:
            flag = true;
            timer.cancel();
        }
    }

}

【问题讨论】:

  • while 循环可能会占用所有 CPU。尝试在最后输入Thread.sleep(16)。如果这不起作用,程序在运行时是否仍然响应?
  • 根据 camickr 的回答,甚至不要使用 while 循环——使用 Swing Timer。

标签: java swing graphics timer keylistener


【解决方案1】:

您的问题是关于 Swing(不是 AWT),所以:

  1. 不要扩展 Canvas。相反,自定义绘画是通过扩展 JPanel 来完成的
  2. 不要覆盖paint(...)。自定义绘画是通过覆盖paintComponent(...)来完成的
  3. 不要使用 TimerTask。而是使用摇摆计时器。
  4. 不要使用 getGraphics() 方法。见第 2 点。
  5. 不要调用更新(...)。您只需在组件上调用 repaint(),它就会自己绘制。
  6. 不要使用 while 循环。这就是使用 Swing Timer 的原因。
  7. 不要以大写字符开头的变量名。遵循 Java 命名约定。
  8. 不要使用 KeyListener。 Swing 旨在与键绑定一起使用。

查看Custom Painting 上的 Swing 教程,了解基本的绘画示例以帮助您入门。

查看Motion Using the KeyboardKeyboard Animation 示例解决了许多此类问题。

【讨论】:

  • 抱歉这么久才回复。非常感谢您的回答,您提供的最后一个链接对我很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多