挥杆计时器未按预期执行

时间:2015-07-28 13:17:53

标签: java swing timer repaint

我被建议不要将sleep用于暂停目的,而是使用swing timer但仍然无效。我想要实现的动画是从左上角开始的球对角线朝向底部。

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

class Show_starter {

    int x, y;
    JFrame window = new JFrame("Graphic_show");
    Graphic_panel jp = new Graphic_panel();

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

    private void go() {
        window.getContentPane().add(BorderLayout.CENTER, jp);
        window.setSize(600,800);
        window.setVisible(true);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    class Graphic_panel extends JPanel {

        public void paintComponent(Graphics g) {

            for ( int i = 0; i < 100; ++i) {
                g.setColor(Color.white);
                g.fillRect(0, 0, this.getWidth(), this.getHeight());
                g.setColor(Color.green);
                g.fillOval(x, y, 40, 40);

                x++;
                y++;

                try {

                    Timer tmr = new Timer(1000, new TimerListener()); //This fires an event after every 1 sec after it has started by start().
                   //But The ball travels too much fast and stops at a point and again travels very fast.
                    tmr.serRepeats(false); // even this is not working.
                    tmr.start();
                    //should i use repaint here or in Listener for this timer?
                } catch (Exception e){}
            }
        }

        class TimerListener implements ActionListener {

            public void actionPerformed(ActionEvent e) {
                jp.repaint();
            }
        }
    }
}

它显示的行为是非常奇怪的球首先以非常高的速度运行并且暂时停在某一点并再次以相同的速度运动。

我还尝试将timer事件的时间更改为触发,但同样的事情发生了。

即使在我开始timer的内部循环中,跟随函数调用也无法正常工作

setRepeats(false);

2 个答案:

答案 0 :(得分:2)

不要创建新的计时器总是一个计时器足够。定时间隔更多.1秒对于动画来说太慢了。你不需要循环而且不要增加x和y在paintcomponet()方法中,因为出于某种原因调用此方法,例如当您调整大小,最小化,最大化时。

意外行为是由于你的循环和创建新的计时器()。例如,在x y中从0开始,但是在第一秒中,在下一个油漆中增加到100,100,你会看到它们在100,100的位置。这看起来像是快速移动然后停止......

示例代码(已编辑)

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

public class Show_starter {

    private Timer tmr;

    int x, y;
    JFrame window = new JFrame("Graphic_show");
    Graphic_panel jp = new Graphic_panel();

    public static void main(String[] args) {

        Show_starter start = new Show_starter();
        start.go();

    }

    private void go() {

        window.getContentPane().add(BorderLayout.CENTER, jp);
        window.setSize(600, 800);
        window.setVisible(true);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        tmr = new Timer(10, new ActionListener() { // time gap in millisecond

            @Override
            public void actionPerformed(ActionEvent ae) {

                jp.increse();
                jp.repaint();
            }
        });
        tmr.start();

    }

    class Graphic_panel extends JPanel {

        public void increse() {
            x++;
            y++;
            if (x > 100) { // stop animation at x>100
                tmr.stop();
            }
        }

        public void paintComponent(Graphics g) {

            g.setColor(Color.white);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
            g.setColor(Color.green);
            g.fillOval(x, y, 40, 40);

        }

    }
}

输出(比那更顺畅)

enter image description here

答案 1 :(得分:0)

首先,您不应在loop内使用paint component

public void paintComponent(Graphics g){
            g.setColor(Color.white);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
            g.setColor(Color.green);
            g.fillOval(x, y, 40, 40);
}

只需绘制它并在课堂上公开xy,以便您可以从外部轻松访问

现在运行runnable(咨询invokelaterswingUtilities)或创建新的Thread

public void run()内做你想做的任何动画。您可以使用循环,但在每次迭代中添加Thread.sleep(//in miliseconds)repaint()

注意:您需要更改xy以及repaint(),以便将其绘制到新位置。并且需要sleep()来减慢执行速度,否则查看者无法看到它。