Java 创建螺旋动画(延迟帮助)

Java 创建螺旋动画(延迟帮助),java,animation,delay,sleep,spiral,Java,Animation,Delay,Sleep,Spiral,注意:我对Java相当陌生,因此如果答案非常简单,请记住:) 我所要做的就是制作一个好看的螺旋动画,就像音乐播放时在Windows Media Player中显示的那样,或者像一个类似于Windows XP屏幕保护程序的动画 我一直在试图找出如何在创建一行和创建另一行之间创建延迟 我希望这个程序以一个黑屏开始,每隔半秒左右,在制作一个很酷的螺旋动画之前,在稍微不同的位置添加一行 我确信有一种方法可以用Thread.Sleep()来做我想做的事我只是不知道怎么做 任何帮助或建议都将不胜感激D 当前

注意:我对Java相当陌生,因此如果答案非常简单,请记住:)

我所要做的就是制作一个好看的螺旋动画,就像音乐播放时在Windows Media Player中显示的那样,或者像一个类似于Windows XP屏幕保护程序的动画

我一直在试图找出如何在创建一行和创建另一行之间创建延迟

我希望这个程序以一个黑屏开始,每隔半秒左右,在制作一个很酷的螺旋动画之前,在稍微不同的位置添加一行

我确信有一种方法可以用Thread.Sleep()来做我想做的事我只是不知道怎么做

任何帮助或建议都将不胜感激D


当前我的代码的图片:

您可以使用我的
动画面板
类,在其中进行绘图。这项技术基于

代码: 下面是
演示
课程:

// Demo.java
import javax.swing.*;
import java.awt.*;

public class Demo
{
  public Demo()
  {
    JFrame frame = new JFrame("Demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new DemonstrationPanel(800, 600));
    frame.setBackground(Color.BLACK);
    frame.setSize(800, 600);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

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

您可以在
AnimationPanel
类中调整
fps
的值,以更改动画的速度。

Swing是单线程环境。当您希望定期更改UI的状态时,需要小心。您需要确保不会以任何方式阻止事件调度线程,这样做将防止处理任何新的绘制事件(以及其他事件),使您的UI看起来像挂起了一样,并确保您正在与事件调度线程同步更新,以确保您不会冒任何竞争条件或其他线程问题的风险

请仔细查看以了解更多详细信息。一个简单的方法是使用,例如

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Spinner {

    public static void main(String[] args) {
        new Spinner();
    }

    public Spinner() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new SpinnerPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class SpinnerPane extends JPanel {

        private float angle;

        public SpinnerPane() {
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    angle -= 5;
                    repaint();
                }
            });
            timer.start();
        }

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

        protected Point calculateOutterPoint(float angel) {

            int radius = Math.min(getWidth(), getHeight());

            int x = Math.round(radius / 2);
            int y = Math.round(radius / 2);

            double rads = Math.toRadians((angel + 90));

            // This determins the length of tick as calculate from the center of
            // the circle.  The original code from which this derived allowed
            // for a varible length line from the center of the cirlce, we
            // actually want the opposite, so we calculate the outter limit first
            int fullLength = Math.round((radius / 2f)) - 4;

            // Calculate the outter point of the line
            int xPosy = Math.round((float) (x + Math.cos(rads) * fullLength));
            int yPosy = Math.round((float) (y - Math.sin(rads) * fullLength));

            return new Point(xPosy, yPosy);

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);

            int diameter = Math.min(getWidth(), getHeight());

            int x = (getWidth() - diameter) / 2;
            int y = (getHeight() - diameter) / 2;
            Point to = calculateOutterPoint(angle);
            g2d.drawLine(x + (diameter / 2), y + (diameter / 2), x + to.x, y + to.y);
            g2d.dispose();
        }

    }

}

使用类似的机制,我已经能够创建等待动画,如


为什么不在这里复制代码呢?你应该使用计时器,而不是在EDT中睡觉。看看GetGraphics不是如何完成自定义绘制的;这可能违反了Swing的单线程规则;您不应处理未创建的图形上下文,这可能会阻止在某些系统上将绘制的内容绘制到屏幕上;这可以通过一个Swing计时器或者更好的动画库(如Trident或其他)轻松完成TiminggFramework@MadProgrammer:查看我得到的是谁的图形。这是一个图像的图形,我得到和画上它,利用双缓冲技术。在这个程序中,我使用自己的渲染线程控制了整个绘画。做同样的事情还有其他方法,但这也是一个很好的方法。如果希望看到这种技术的实际应用,可以在IDE中测试该程序。g=this.getGraphics();显然是组件图形上下文,您将图像绘制到它,在EDT之外…您无法控制绘制过程。在任何时候,“重新绘制管理器”都可能过度绘制您所做的操作,导致闪烁。Swing组件已经是双缓冲的。就目前情况而言,这是一个很好的例子,说明不该做什么do@MadProgrammer:井摆计时器不如此方法快。对于基于Swing的组件,不建议使用
getGraphics()
,但我得到的是
图像的图形。那是完全不同的事情。此代码独立于任何第三方库。1-this.getGraphics获取EDT之外的组件图形上下文。这很简单。此方法可以返回null,并且重绘管理器可以随时重写内容。2-摆动计时器的唯一额外开销是动作事件与EDT的同步。我敢打赌,如果包含一个InvokeLater,它将与Swing计时器几乎相同。您可以在执行Thread.sleep调用之前调用repaint来完成此操作
// Demo.java
import javax.swing.*;
import java.awt.*;

public class Demo
{
  public Demo()
  {
    JFrame frame = new JFrame("Demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new DemonstrationPanel(800, 600));
    frame.setBackground(Color.BLACK);
    frame.setSize(800, 600);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      @Override
      public void run()
      {
        new Demo();
      }
    });
  }
}
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Spinner {

    public static void main(String[] args) {
        new Spinner();
    }

    public Spinner() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new SpinnerPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class SpinnerPane extends JPanel {

        private float angle;

        public SpinnerPane() {
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    angle -= 5;
                    repaint();
                }
            });
            timer.start();
        }

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

        protected Point calculateOutterPoint(float angel) {

            int radius = Math.min(getWidth(), getHeight());

            int x = Math.round(radius / 2);
            int y = Math.round(radius / 2);

            double rads = Math.toRadians((angel + 90));

            // This determins the length of tick as calculate from the center of
            // the circle.  The original code from which this derived allowed
            // for a varible length line from the center of the cirlce, we
            // actually want the opposite, so we calculate the outter limit first
            int fullLength = Math.round((radius / 2f)) - 4;

            // Calculate the outter point of the line
            int xPosy = Math.round((float) (x + Math.cos(rads) * fullLength));
            int yPosy = Math.round((float) (y - Math.sin(rads) * fullLength));

            return new Point(xPosy, yPosy);

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);

            int diameter = Math.min(getWidth(), getHeight());

            int x = (getWidth() - diameter) / 2;
            int y = (getHeight() - diameter) / 2;
            Point to = calculateOutterPoint(angle);
            g2d.drawLine(x + (diameter / 2), y + (diameter / 2), x + to.x, y + to.y);
            g2d.dispose();
        }

    }

}