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