java简单的弹跳球闪烁

时间:2017-11-10 02:58:16

标签: java

这只是一个简单的红球上下起伏,我看到它在闪烁。我已经看过很少的主题,但没有找到任何帮助我的答案。 谢谢:))

使用go方法的Window类使球上下移动。 该面板还包含球位置并且只是重新绘制。

Window.java

import java.awt.Dimension;
import javax.swing.JFrame;

public class Window extends JFrame 
{
    public static void main(String[] args) 
    {
        new Window();
    }

    public Panel pan = new Panel();

    public Window() 
    {
        this.setSize(600, 600);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setContentPane(pan);
        this.setVisible(true);

        go();
    }

    private void go() 
    {
        int vecY = 1;
        while (true) 
        {
            if (pan.y <= 100)
            {
                vecY = 1;
            }
            else if (pan.y >= 400)
            {
                vecY = -1;
            }
            pan.y += vecY;
            pan.repaint();
            try 
            {
                Thread.sleep(10);
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }
    }
}

Panel.java

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

public class Panel extends JPanel 
{

  public int x = 300;
  public int y = 300;

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

}

1 个答案:

答案 0 :(得分:1)

存在许多可能的问题。主要问题可能是您的while-looppaintComponent方法之间的线索竞争条件。

while-loop能够在y有机会描绘其状态之前更改paintComponent位置的状态。绘画是在paint子系统的休闲时间完成的,因此调用repaint只是向RepaintManager发出请求,该请求决定了实际绘制周期可能发生的时间和时间,这意味着你可能会掉线帧。

对于Swing中的大多数动画,Swing Timer更有能力。从内部更新UI是安全的,因为ActionListener在EDT的上下文中被调用但不会阻止EDT

例如:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Window extends JFrame {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Window();
            }
        });
    }

    public Panel pan = new Panel();

    public Window() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setContentPane(pan);
        pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);

        go();
    }

    private void go() {
        Timer timer = new Timer(10, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                pan.updateAnmationState();
            }
        });
        timer.start();
    }

    public class Panel extends JPanel {

        private int x = 300;
        private int y = 300;

        private int vecY = 1;

        public void updateAnmationState() {
            if (y <= 100) {
                vecY = 1;
            } else if (y >= 400) {
                vecY = -1;
            }
            y += vecY;
            repaint();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.white);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
            g.setColor(Color.red);
            g.fillOval(x, y, 50, 50);
        }

    }
}

这个例子对MiniMac来说很好用