Java 执着于设计

Java 执着于设计,java,swing,timer,Java,Swing,Timer,我有一个小的GUI java程序,我正在工作,但如何设计各部分应该一起工作让我感到沮丧。基本上,我需要做的是在面板上画一辆“汽车”,然后将面板连接到框架上。然后设置面板动画,以产生移动的错觉 我的问题是,我不知道如何将制作动画的代码移动到它自己的类中。当我开始做这个的时候,我先做了UI元素。然后我遇到了Timer类,并在一个UI元素类(CarBody)中使用了该类。我的代码现在的工作方式是,只要我运行这个程序,“汽车”就开始移动,因为我没有将它设置为通过按下按钮触发。我不明白如何将动画代码移动到

我有一个小的GUI java程序,我正在工作,但如何设计各部分应该一起工作让我感到沮丧。基本上,我需要做的是在面板上画一辆“汽车”,然后将面板连接到框架上。然后设置面板动画,以产生移动的错觉

我的问题是,我不知道如何将制作动画的代码移动到它自己的类中。当我开始做这个的时候,我先做了UI元素。然后我遇到了Timer类,并在一个UI元素类(CarBody)中使用了该类。我的代码现在的工作方式是,只要我运行这个程序,“汽车”就开始移动,因为我没有将它设置为通过按下按钮触发。我不明白如何将动画代码移动到它的on类中,并通过按下按钮触发它

如果我能在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();

        }
    }
}
如果我能在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) );
    }
}
import java.awt.*;
导入java.awt.event.*;
导入javax.swing.*;
公共类TimerAnimation扩展JLabel实现ActionListener
{
int deltaX=2;
int deltaY=3;
int方向x=1;
int方向y=1;
公共定时(
int startX,int startY,
int deltaX,int deltaY,
int directionX,int directionY,
整数延迟)
{
this.deltaX=deltaX;
this.deltaY=deltaY;
this.directionX=directionX;
this.directionY=directionY;
设置图标(新的图像图标(“dukewaveed.gif”);
//设置图标(新的图像图标(“copy16.gif”);
设置大小(getPreferredSize());
设置位置(startX、startY);
新的javax.swing.Timer(delay,this.start();
}
已执行的公共无效操作(操作事件e)
{
容器父级=getParent();
//确定下一个X位置
int-nextX=getLocation().x+(deltaX*方向x);
如果(nextX<0)
{
nextX=0;
方向x*=-1;
}
if(nextX+getSize().width>parent.getSize().width)
{
nextX=parent.getSize().width-getSize().width;
方向x*=-1;
}
//确定下一个Y位置
int nextY=getLocation().y+(deltaY*directionY);
if(nextY<0)
{
nextY=0;
方向y*=-1;
}
if(nextY+getSize().height>parent.getSize().height)
{
nextY=parent.getSize().height-getSize().height;
方向y*=-1;
}
//移动标签
设置位置(nextX、nextY);
}
公共静态void main(字符串[]args)
{
JPanel面板=新的JPanel();
JFrame=新JFrame();
frame.setContentPane(面板);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
//frame.getContentPane().add(新的TimerAnimation(10,10,2,3,1,1,10));
frame.getContentPane().add(新的TimerAnimation(3001003,2,-1,1,20));
//frame.getContentPane().add(新的TimerAnimation(0,000,5,0,1,1,20));
frame.getContentPane().add(新的TimerAnimation(0,200,5,0,1,1,80));
框架。设置尺寸(400400);
frame.setLocationRelativeTo(空);
frame.setVisible(true);
//frame.getContentPane().add(新的TimerAnimation(10,10,2,3,1,1,10));
//frame.getContentPane().add(新的TimerAnimation(10,10,3,0,1,1,10));
}
}

本例不进行自定义绘制,动画是通过调用标签上的setlocation(…)方法完成的,这将导致重新绘制(),因此解决方案与您的略有不同,但关键点是不要更改paintComponent()中的位置值方法。

Amen:paintComponent仅用于绘制,不应包含任何程序逻辑。原始海报必须意识到,他无法完全控制何时或是否调用此方法。