[英]Java drawing a circle using awt,JFrame with Thread(Runnable) on Netbeans (Mac)
https://github.com/terryaa/KOSTA_MAC/tree/master/Java/NetBeans/day13_01_15/src/ex1
我想做的是绘制圆,但是一次在画布上绘制一个圆,然后使用Runnable join继续绘制下一个圆。 它应该使用.start()绘制一个圆,而其他.start()不应在正式.start()的绘制圆完成之前开始。
在链接页的程序包中,Ex3_Canvas1类具有main并使用Runnable MyThread0类使用基本的.start()和.join()绘制圆,它可以完美实现我想要的功能。
我创建了NetBean的自动JFrame类Ex2_CanvasDemo并尝试执行同样的操作,但失败了。 绘制一个完整的圆后,将弹出“ JFrame”窗口,然后显示创建下一个圆。 我想要的是该窗口应该首先出现,并且它显示了两个圆的创建,而不是同时显示,而是依次显示,例如Ex3_Canvas1。
我猜这是因为主线程等待th(Ex2_CanvasDemo)完成,所以窗口不适用于更改。 但是Ex1_Canvas1不应该这样做吗? 这种差异是由于netbeans自动生成的代码引起的吗? 如何与Ex2_CanvasDemo中的Ex1_Canvas1相同。
我尝试制作一个Runnable类并在Ex2_CanvasDemo中使用,但也失败了。
有什么帮助吗? 我在Mac上使用jdk 8和netbeans8。
-Ex2_CanvasDemo的螺纹部分-
public Ex2_CanvasDemo() {
initComponents();
Thread th=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<370;i+=10){
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(Ex2_CanvasDemo.class.getName()).log(Level.SEVERE, null, ex);
}
arcNUm=i;
System.out.println("circle"+arcNUm);
canvas1.repaint();
}
}
});
th.start();
try {
th.join();
} catch (InterruptedException ex) {
Logger.getLogger(Ex2_CanvasDemo.class.getName()).log(Level.SEVERE, null, ex);
}
th=new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<370;i+=10){
System.out.println("circle"+i);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(Ex2_CanvasDemo.class.getName()).log(Level.SEVERE, null, ex);
}
arcNum2=i;
canvas2.repaint();
}
}
});
th.start();
// try {
// th.join();
// } catch (InterruptedException ex) {
// Logger.getLogger(Ex2_CanvasDemo.class.getName()).log(Level.SEVERE, null, ex);
// }
}
动画很难,好的动画真的很难。 您需要自己重复一遍,因为正确完成动画非常困难。
动画基本上是随着时间变化的幻觉。 您很少执行线性动画,动画通常需要一段时间才能完成,因为它可以消除平台上的性能差异,这对用户而言并不那么苛刻。
摆动是单线程的,不是线程安全的。 这意味着您不应该阻塞事件分发线程,而只能从事件分发线程的上下文中更新UI。
有关更多详细信息,请参见Swing中的并发。
这给生活带来了一些困难,因为您不能简单地在EDT中运行线性循环,因为这会阻塞UI,并且很难从Thread
因为这是一团糟的同步。
最简单的解决方案之一是利用可用的API并使用Swing Timer
,该Timer
充当伪循环,从而在回叫之间间隔一小段时间,您可以在其中执行一些操作
尽管有多种方法可以解决此问题,但我设置了一个简单的List
,其中包含一堆Animatable
,可以“执行任务”,然后简单地依次串行运行。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane testPane = new TestPane();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(testPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
testPane.play();
}
});
}
});
}
public class TestPane extends JPanel {
private List<Animatable> animations;
private Animatable animation;
private Timer timer;
public TestPane() {
animations = new ArrayList<>(25);
animations.add(new CircleAnimation(Color.RED));
animations.add(new CircleAnimation(Color.BLUE));
timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (animation == null) {
animation = animations.remove(0);
}
if (animation.update(getBounds())) {
if (animations.isEmpty()) {
((Timer)e.getSource()).stop();
} else {
animation = animations.remove(0);
}
}
repaint();
}
});
}
public void play() {
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (animation != null) {
Graphics2D g2d = (Graphics2D) g.create();
animation.paint(g2d);
g2d.dispose();
}
}
}
public interface Animatable {
public boolean update(Rectangle bounds);
public void paint(Graphics2D g2d);
}
public class CircleAnimation implements Animatable {
private Color color;
private Ellipse2D circle;
private double delta = -1;
public CircleAnimation(Color color) {
this.color = color;
}
@Override
public boolean update(Rectangle bounds) {
if (circle == null) {
circle = new Ellipse2D.Double(bounds.width, (bounds.height / 2) - 10, 20, 20);
}
Rectangle rect = circle.getBounds();
rect.x += delta;
circle.setFrame(rect);
return rect.x + 20 < bounds.x;
}
@Override
public void paint(Graphics2D g2d) {
if (circle == null) {
return;
}
g2d.setColor(color);
g2d.fill(circle);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.