如何使用Java中的Timer类在面板上移动对象

时间:2014-07-24 17:15:11

标签: java swing timer

我有一个关于用Java制作汽车模拟程序的任务。我目前在地图上移动汽车时遇到了麻烦。 这是Map(main)类的代码

import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;

import project.Car;
public class Map extends JPanel {

public static void main(String[] args)
{
JFrame f = new JFrame();
f.setSize(800, 450);
f.add(new Map());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);

Car carA = new Car();
Car carB = new Car();    

/*
int rX = randX();
carA.positionX = carA.setPositionX(rX);

System.out.println(carA.getPositionX());
*/  
}

public static int randX()
{
  Random rnX = new Random();

  int randomX = rnX.nextInt((40 - 0) + 1) + 0;

  if (randomX >= 0 && randomX <= 4 || randomX == 20 && randomX <= 24  || randomX >= 25)
  {
      randX();
  }

  return randomX;
 }

 public static int randY()
 {
  Random rnY = new Random();

  int randomY = rnY.nextInt((55 - 15) + 1) + 15;

  if (randomY >= 0 && randomY <= 4 || randomY >= 25 && randomY <= 29 || randomY >= 30)
  {
      randY();
  }

  return randomY;
}

//paint a = new paint();

public void paint(Graphics g)
{
g.drawRect (0 , 0, 500,200); //
g.drawRect (20, 25, 450,150); // The road
g.drawRect (40, 50, 400,100); //

g.drawRect (10 , 10, 8,8); //One of the car's initialization

}

}

这是Car class

import java.awt.Graphics;
import java.awt.Toolkit;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Timer;
import java.util.TimerTask;


public class Car extends JPanel
{
int positionX = 0;
int positionY = 0;
int weight = 0;
//int lane = 0;

public int getPositionX()
{
    return positionX;
}

public int setPositionX(int newPosX)
{
    positionX = newPosX;
    return positionX;
}

public int getPositionY()
{
    return positionY;
}

public int setPositionY(int newPosY)
{
    positionY = newPosY;
    return positionY;
}

public int Accelerate()
{
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    Timer timer = new Timer();
    timer.schedule(new RemindTask(), 0, //initial delay
    1 * 1000); //subsequent rate
    //schedule(TimerTask task, long delay);
    return positionX;
}

class RemindTask extends TimerTask 
{
//int numWarningBeeps = 3;

public void run()
{
    if(positionX <= 450 && positionY <= 23)
    {
        positionX += 1;
    }
    else if(positionX == 450 && positionY <= 23)
    {
        positionY+= 1;
    }
    else if(positionY <= 150 && positionX >= 15)
    {
        positionX -= 1;
    }
    else if(positionY == 150 && positionX == 23)
    {
        positionY -= 1;
    }
}
}

public static int main(int[] args)
{

    return 0;
}
}

看起来,我不知道如何应用我制作的计时器,也不知道它是否有效。 请给我一些关于如何应用计时器的指导,以便汽车可以在指定区域内移动..

2 个答案:

答案 0 :(得分:3)

  1. 我不会让每辆车成为一个小组。你必须处理定位面板,调整它们的大小,可能将它们分层,除其他外,IMO是不必要的,可能过于复杂并导致问题。

    相反,只需使用一个面板作为绘画表面,并创建一个将成为模型的类;模型在某种意义上说它只是负责控制汽车的状态。它还可以有一个渲染汽车的方法,但实际渲染将委托给主面板的图形上下文。

  2. 不要使用java.util.Timer。而是使用javax.swing.Timer,它更适合处理重新绘制UI,以及与Swing相关的其他内容。您可以在How to use Swing Timers查看更多信息。基本上,您所做的就是将确定的延迟和ActionListener传递给Timer构造函数。每次滴答(延迟),都会调用ActionListener的actionPerformed。这是你将改变汽车状态并重新绘制主要绘画表面的地方。

  3. 您可以在this answer

    中查看上述各点的示例

    enter image description here

答案 1 :(得分:0)

为什么有一个方法在一个应该用作Object的类中返回一个整数?

看起来你这样做是因为你习惯了C ++,因为Java中的主要方法不返回值,而是无效。所以它应该是:

public static void main(String[] args) {
     //code here, don't return anything
}

我看到你在实际的主类Map中使用它,但我觉得没必要这样做。

无论如何,你不应该在你的汽车课上有一个主力。

在你的整体代码中,你甚至没有要求任何一辆车移动(我认为是Accelerate()方法)

您是否尝试过为两个Car实例调用Accelerate()?

此外,在Accelerate()方法中,您无缘无故地获取Default Toolkit。你应该删除它。

您还在Accelerate中返回一个int,但它将返回与之前相同的位置。为什么?计时器在另一个线程上运行。您将在一秒钟后设置汽车位置,然后在安排任务后返回位置。

我不会说这是一个大问题,因为你仍在设置位置,但我建议将Accelerate返回void而不是整数。

除此之外,你不应该像这样使用Timers或使用JFrame绘画功能,而是使用JPanel来渲染你想要的所有对象。使每个对象呈现为JPanel并不是一个好主意。