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

How Do I Paint My 2D Objects Within A Timer

我正在尝试使用 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

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

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

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

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

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

因为 Graphics 本身也是瞬态的,你不应该在 paint 方法的范围之外维护对它的引用。

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

例如见