基本动画未执行

时间:2012-02-14 13:02:13

标签: java swing animation

我正在学习java。这是我的第一部动画。我想要一个球在按下开始按钮时连续上下移动,当按下停止按钮时它应该STOP。我写的代码将球移动5次(向下3次,向上2次)。但面板仅显示开始和最终位置,它不显示中间位置。如何显示中间位置?

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

public class dabble
{
    private boolean z = true;
    private int x=10;
    private int y=10;
    private JFrame frame;
    private JLabel label;
    private mypanel panel;
    private JButton b1;
    private JButton b2;

    public static void main (String[] args)
    {
        dabble dab = new dabble();
        dab.start();
    }

    void start()
    {
        frame = new JFrame();
        label = new JLabel();
        panel = new mypanel();
        b1= new JButton("Start");
        b2= new JButton("Stop");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        b1.addActionListener(new al1());
        b2.addActionListener(new al2());

        frame.getContentPane().add(BorderLayout.NORTH,b1);
        frame.getContentPane().add(BorderLayout.SOUTH,b2);
        frame.getContentPane().add(BorderLayout.CENTER,panel);
        frame.getContentPane().add(BorderLayout.EAST,label);
        frame.setSize(600,600);
        frame.setVisible(true);
    }

    void go()
    {
        for(int i=0;i<5;i++)
        {
            if(z==false)
                break;
            //label.setText("Hi");
            y=510-y;
            panel.repaint();
            try{
                Thread.sleep(500);
                //label.setText("sleep");
            }catch(Exception Ex)
            {
             //label.setText("exp");
            }
        }
    }

    class al1 implements ActionListener{
        public void actionPerformed(ActionEvent event){
            go();
        }
    }

    class al2 implements ActionListener{
        public void actionPerformed(ActionEvent event){
            z=false;
        }
    }

    class mypanel extends JPanel 
    {
        public void paintComponent ( Graphics g)
        {
            g.setColor(Color.white);
            g.fillRect(0,0,this.getWidth(),this.getHeight());
            int red = (int) (Math.random()*255);
            int green = (int) (Math.random()*255);
            int blue = (int) (Math.random()*255);
            Color c1 = new Color(red,green,blue);
            g.setColor(c1);
            g.fillOval(x,y,20,20);
        }
    }
}

2 个答案:

答案 0 :(得分:2)

调用repaint()实际上并没有绘制面板 - 它只是标记它以后绘制。并且绘制总是发生在事件调度线程上,事件侦听器通知也是如此。

由于在事件调度线程(通过按钮操作侦听器)上调用go(),因此在go()运行时无法重新绘制面板。您只需将go()完成后的一次重绘排队。

您可能想要做的是使用每500毫秒触发一次的javax.swing.Timer,并且其行动是将球移动一步然后调用repaint()

答案 1 :(得分:0)

你执行你的循环5次(而不是无限循环)。此外,您将垂直位置从10更改为500,然后再更改为10等...如果要查看中间位置,则应考虑重新绘制中间位置以及提供y的中间值。

好的,执行以下操作可以解决您的问题,但这绝对是一个糟糕的设计:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class dabble {

    private static final long ANIMATION_DURATION = 5000; // 5 seconds
    private static final int REFRESH_RATE = 10;// 10 times per second
    private boolean incrementing = true;
    private volatile boolean z = true;
    private int x = 10;
    private volatile int y = 10;
    private JFrame frame;
    private JLabel label;
    private mypanel panel;
    private JButton b1;
    private JButton b2;

    public static void main(String[] args) {
        dabble dab = new dabble();
        dab.start();
    }

    void start() {
        frame = new JFrame();
        label = new JLabel();
        panel = new mypanel();
        b1 = new JButton("Start");
        b2 = new JButton("Stop");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        b1.addActionListener(new al1());
        b2.addActionListener(new al2());

        frame.getContentPane().add(BorderLayout.NORTH, b1);
        frame.getContentPane().add(BorderLayout.SOUTH, b2);
        frame.getContentPane().add(BorderLayout.CENTER, panel);
        frame.getContentPane().add(BorderLayout.EAST, label);
        frame.setSize(600, 600);
        frame.setVisible(true);
    }

    void go() {
        new Animation().start();
    }

    class al1 implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent event) {
            go();
        }
    }

    class al2 implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent event) {
            z = false;
        }
    }

    class mypanel extends JPanel {
        @Override
        public void paintComponent(Graphics g) {
            g.setColor(Color.white);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
            int red = (int) (Math.random() * 255);
            int green = (int) (Math.random() * 255);
            int blue = (int) (Math.random() * 255);
            Color c1 = new Color(red, green, blue);
            g.setColor(c1);
            g.fillOval(x, y, 20, 20);
        }
    }

    class Animation extends Thread {

        private long start;

        @Override
        public void run() {
            start = System.currentTimeMillis();
            while (true) {
                if (!z) {
                    return;
                }
                double progress = (double) (System.currentTimeMillis() - start) / ANIMATION_DURATION;
                System.err.println(progress);
                if (incrementing) {
                    y = (int) (10 + 500 * progress);
                } else {
                    y = (int) (510 - 500 * progress);
                }
                if (progress > 1.0) {
                    start = System.currentTimeMillis();
                    incrementing = !incrementing;
                }

                panel.repaint();
                try {
                    Thread.sleep(1000 / REFRESH_RATE);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}