坚持设计

时间:2011-04-16 23:49:38

标签: java swing timer

我正在研究一个小的GUI java程序,但设计这些部分应该如何协同工作让我感到沮丧。基本上我需要做的是在面板上画一个“汽车”并将该面板连接到框架上。然后为面板设置动画,以产生运动的幻觉。

我的问题是我不明白如何将动画的代码移动到它自己的类。当我开始研究这个时,我首先制作了UI元素。然后我遇到了Timer类,并将该类用于本应该只是一个UI元素类(CarBody)。我的代码现在的工作方式是,一旦我运行程序,“汽车”开始移动,因为我没有将它设置为按下按钮触发。我不明白如何将动画代码移动到它上面的类,并按下按钮触发它。

如果我可以在performAction()方法中调用repaint(),我可以在两秒内解决这个问题。问题是我做不到!它不会那样编译。

我所做的是

class CarBody extends JPanel {
    private int xCoordinate = 0;
    CarBody(){
        Timer timer = new Timer(1000,new TimerListener());
        timer.start();

}

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        //g.fillRect(10, 10, 60, 50);

        if(xCoordinate > getWidth()){
            xCoordinate = -20;
        }
        xCoordinate +=100;
        g.fillRect(xCoordinate,10,60,50);

}

    class TimerListener implements ActionListener{
        public void actionPerformed(ActionEvent e){
            repaint();

        }
    }
}

1 个答案:

答案 0 :(得分:2)

  

如果我可以在performAction()方法中调用repaint(),我可以在两秒内解决这个问题。

您不应该在paintComponent()方法中更改汽车坐标。您应该有一个方法来设置坐标,然后重新绘制汽车。

创建ActionListener类时,将要重新绘制的面板作为参数传递给类。然后你可以调用“changeLocation”方法,它将更新汽车的位置,然后自己调用repaint()。

对于另一种方法,您可以向标签添加图标,只需更改标签的位置,它就会自动重新绘制。这是一个简单的例子:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TimerAnimation extends JLabel implements ActionListener
{
    int deltaX = 2;
    int deltaY = 3;
    int directionX = 1;
    int directionY = 1;

    public TimerAnimation(
        int startX, int startY,
        int deltaX, int deltaY,
        int directionX, int directionY,
        int delay)
    {
        this.deltaX = deltaX;
        this.deltaY = deltaY;
        this.directionX = directionX;
        this.directionY = directionY;

        setIcon( new ImageIcon("dukewavered.gif") );
//      setIcon( new ImageIcon("copy16.gif") );
        setSize( getPreferredSize() );
        setLocation(startX, startY);
        new javax.swing.Timer(delay, this).start();
    }

    public void actionPerformed(ActionEvent e)
    {
        Container parent = getParent();

        //  Determine next X position

        int nextX = getLocation().x + (deltaX * directionX);

        if (nextX < 0)
        {
            nextX = 0;
            directionX *= -1;
        }

        if ( nextX + getSize().width > parent.getSize().width)
        {
            nextX = parent.getSize().width - getSize().width;
            directionX *= -1;
        }

        //  Determine next Y position

        int nextY = getLocation().y + (deltaY * directionY);

        if (nextY < 0)
        {
            nextY = 0;
            directionY *= -1;
        }

        if ( nextY + getSize().height > parent.getSize().height)
        {
            nextY = parent.getSize().height - getSize().height;
            directionY *= -1;
        }

        //  Move the label

        setLocation(nextX, nextY);
    }

    public static void main(String[] args)
    {
        JPanel panel = new JPanel();
        JFrame frame = new JFrame();

        frame.setContentPane(panel);
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.getContentPane().setLayout(null);
//      frame.getContentPane().add( new TimerAnimation(10, 10, 2, 3, 1, 1, 10) );
        frame.getContentPane().add( new TimerAnimation(300, 100, 3, 2, -1, 1, 20) );
//      frame.getContentPane().add( new TimerAnimation(0, 000, 5, 0, 1, 1, 20) );
        frame.getContentPane().add( new TimerAnimation(0, 200, 5, 0, 1, 1, 80) );
        frame.setSize(400, 400);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
//      frame.getContentPane().add( new TimerAnimation(10, 10, 2, 3, 1, 1, 10) );
//      frame.getContentPane().add( new TimerAnimation(10, 10, 3, 0, 1, 1, 10) );
    }
}

这个例子,不做自定义绘画,动画是通过调用标签上的setlocation(...)方法完成的,这会导致重绘()所以解决方案与你的略有不同,但关键点不要更改paintComponent()方法中的位置值。