简体   繁体   English

使用java.swingTimer重复动画

[英]repeating animation using java.swingTimer

I am writing the code of Game bean machine (Galton box) using animated graphics. 我正在使用动画图形编写Game Bean机器(加尔顿盒)的代码。 I am using swing.Timer to make the red ball move, by letting the Timer object take an ActionListener. 我正在使用swing.Timer,通过让Timer对象采用ActionListener来使红球移动。

Here is the output: The red ball here is moving randomly : http://imgur.com/J9Xq0t5&HIv1udp And here it reaches the bottom: http://imgur.com/J9Xq0t5&HIv1udp#1 输出为:这里的红球随机移动: http : //imgur.com/J9Xq0t5&HIv1udp并到达底部: http : //imgur.com/J9Xq0t5&HIv1udp#1

The problem is that I want to make several balls moving not only 1 but I actually cannot, I tried to put the Timer object in a loop but it only speeded up the ball motion. 问题是我想使多个球不仅移动1,但实际上却不能移动,我试图将Timer对象置于一个循环中,但这只会加快球的运动。

Here is the code I wrote: 这是我写的代码:

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.util.Scanner;
import javax.swing.*;


public class GameBean extends JFrame{
private int nSlots;
private int balls;

public GameBean (int nSlots, int balls){
    this.balls=balls;
    this.nSlots=nSlots;
    Timer timer=new Timer(500,new RandomListener());

    timer.start();

    JPanel panel = new JPanel();

    this.add(canvas); 
}

Ball canvas = new Ball();


 public static void main(String[] args) {

    Scanner input=new Scanner(System.in);

    System.out.println("Please enter number of slots: ");
    int nSlots=input.nextInt();

    JFrame frame = new GameBean (nSlots, 5);

    frame.setTitle("Bean Game Machine");
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    frame.setSize(300, 500);
    frame.setVisible(true);

   }
 class RandomListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
         canvas.moveRandom();
    }
}


class Ball extends JPanel{
    Random rand=new Random();
    private int n;
    private int raduis = 10;
    private int moveRaduis=12;
    private int L = 0;
    private int R = 0;
    private int D = 0;


    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.RED);

        g.fillOval(getWidth()/2 -raduis/2  + R + L, 0 + D , moveRaduis, moveRaduis);

        repaint();
        int  i=0;
        int width=(getWidth()/8);
        int space=(getWidth()-nSlots*30)/2;
        g.setColor(Color.BLACK);
        for(i=0;i<=nSlots;i++){
            g.drawLine(space+(30*i),getHeight()-balls*(raduis) ,space+(30*i) ,getHeight() );
            if(i!=0 && i!=nSlots)
                g.fillOval(space+(30*i)-5, getHeight()-balls*(raduis)-5, 10, 10);
            if(i==0){
                g.drawLine(space,getHeight()-balls*(raduis) , space+((nSlots)*15)-(raduis/2)-15 , getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2);
                g.drawLine(space+((nSlots)*15)-(raduis/2)-15 , getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2 , space+((nSlots)*15)-(raduis/2)-15 , getHeight()/2-nSlots*nSlots);//vertical line

            }
            if(i==nSlots){
                g.drawLine(space+(30*i), getHeight()-balls*(raduis), space+((nSlots)*15)+(raduis/2)+15, getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2);
                g.drawLine(space+((nSlots)*15)+(raduis/2)+15 , getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2 , space+((nSlots)*15)+(raduis/2)+15 , getHeight()/2-nSlots*nSlots);//vertical line

            }

        }


        int o=1;
        for(i=1;i<=nSlots-2;i++){
            int k=2;
            for(int j=i;j<=nSlots-2;j++){
                g.fillOval(space+((i+k)*15)-raduis/2, getHeight()-(balls*raduis)-(30*o)-raduis/2, raduis, raduis); 
                k=k+2;   
             }o++;
        }

      }

    public void moveRandom(){

        n=1+rand.nextInt(100);
        if(n<=51){
            D+=15;

            if(D<=(getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2))//if(D<=14*15)
                L=0;
            else if(D>getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2 && D<getHeight()-balls*(raduis))
            {
                D+=15;
                L-=15;

            }
            else if(D>=getHeight()-balls*(raduis))
            {
                if(D==31*15)D-=15;
                D=D;

            }

        }
        else if (n>=51 && n<=100){
            D+=15;
            if(D<=getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2)
                R=0;
            else if(D>getHeight()-15-(balls*raduis)-(30*(nSlots-2))-raduis/2 && D<getHeight()-balls*(raduis))
                {
                D+=15;
                R+=15;
            }
            else if(D>=getHeight()-balls*(raduis)){

                if(D==31*15)D-=15;
                D=D;

            }

        }

    }
    } 

    }

Any HELP please ! 任何帮助,请! Thanks all.. 谢谢大家

Here's a suggestion. 这是一个建议。

Don't make each ball extends JPanel . 不要让每个ball伸出JPanel Just make it a class for holding/manipulating/drawing the state. 只需将其设为用于保持/操纵/绘制状态的类即可。

Ball.java (notice Java naming convention) Ball.java(注意Java命名约定)

public class Ball {
    int x, y; // and whatever other state you need

    public Ball(int x, int y {}  // or however you want to construct the ball

    public void draw(Graphics g) {
        // draw ball here
    }
    public void move() {
        // do calculations to move here
    }
}

Then just have one BallPanel class that extends JPanel and do the painting there. 然后只有一个BallPanel类可以扩展JPanel并在那里进行绘画。 Just hold a List<Ball> in the class and you can call each Ball 's draw() method in the paintComponent and each Ball 's move() method in the Timer . 只需拿着一个List<Ball>的类,你可以调用每个Balldraw()的方法paintComponent和每个Ballmove()方法的Timer You could even dynamically add balls to be animated by just adding a new Ball to the list. 您甚至可以通过向列表中添加新的Ball来动态添加要动画的Ball Something like 就像是

public class BallPanel extends JPanel {
    private List<Ball> balls;  // create the list

    public BallPanel() {
        Timer timer = new Timer(40, new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                for (Ball ball: balls) {
                    ball.move();
                }
                repaint();
            }
        });
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Ball ball : balls) {
            ball.draw(g);
        }
    }
}

This way you don't have to worry above separate timers and layering panels. 这样,您不必担心单独的计时器和分层面板上方的问题。

See a bunch of complete example, using this technique, here and here and here and here and here and here . 在此处此处此处此处此处此处看到使用此技术的大量完整示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM