java - 如何在计时器内绘制 2D 对象

标签 java swing paintcomponent

我正在尝试使用 OOP 制作贪吃蛇游戏。 OOP 对我来说是一个新概念,因为我通常使用函数式编程。

我有一个计时器,当它执行时,它应该绘制蛇和食物。

@Override
protected void paintComponent(Graphics g) {

    Timer timer = new Timer();

    TimerTask timerTask = new TimerTask() {

        @Override
        public void run() {

            //SNAKE AND FOOD DO NOT SHOW UP HERE

            g.setColor(Color.GREEN);
            drawSnake(g, snek);
            drawFood(g, foodPack);  
            snek.changeYDir(10);
            snek.moveHeadY();
            System.out.println("Timer is running");
            System.out.println(snek.getHeadY());
            System.out.println(snek.getChunkX(0));

        }
    };
    timer.scheduleAtFixedRate(timerTask, 0, 1000);



    //If code in timer is put here, snake and food show up


}

**我推断出的一些线索!

  1. 计时器正在运行
  2. 头部正在移动 - 显示在控制台中
  3. 蛇身存在 - 显示在控制台中存在

控制台日志:

Timer is running
340
130

这是整个项目的链接。 https://files.fm/u/b8kvgebq

最佳答案

首先阅读 Painting in AWT and SwingPerforming Custom Painting更好地了解 Swing 中绘画的实际工作原理。

接下来,请阅读 Concurrency in Swing了解线程在 Swing 中的工作原理。

paintComponent 应该只绘制组件的当前状态,它不应该执行任何可能触发新绘制 channel 的操作。

由于 paintComponent 可以出于多种原因随时调用,其中许多原因是您无法控制的,因此尝试在其中安排新的 TimerTask 是一个非常非常糟糕的主意。您最终可能会遇到任意数量的计时器尝试更改 UI,这会降低性能并可能相互冲突。

由于 Graphics 本身也是 transient 的,因此您永远不应该在 paint 方法的范围之外维护对它的引用。

首先,看一下How to use Swing Timers以获得更好的基础解决方案。您应该创建一个 Timer 来更新组件的状态并调用 repaint,这将间接调用您的 paintComponent,此时您将绘制组件的当前状态。

例如参见SnakeGame how to make the tail follow the head?

关于java - 如何在计时器内绘制 2D 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52909172/

相关文章:

java - 随机弹跳球

java - 在 Java Applet 中调用 Web 服务方法

java - 为什么我没有被警告这个问题?

java - Swing 中两个线程上的同步块(synchronized block)不起作用

Java面板界面

java - java小程序中的paint()无故被调用两次

java - 已知为非空值的冗余空值检查或 findbugs 中可能存在的错误

java - JTable读取空值

另一个面板上的 Java 透明面板

java - 我正在制作动画的这个正方形在它后面留下了痕迹,任何人都可以找出原因吗?