简体   繁体   English

Java在NetBeans(Mac)上使用awt,JFrame和Thread(Runnable)绘制圆

[英]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 https://github.com/terryaa/KOSTA_MAC/tree/master/Java/NetBeans/day13_01_15/src/ex1

What I'm trying to do is to draw circles, but one circle on a canvas at a time and then moving on to drawing next circle using Runnable join. 我想做的是绘制圆,但是一次在画布上绘制一个圆,然后使用Runnable join继续绘制下一个圆。 It should draw a circle using .start() and the other .start() shouldn't start until formal .start()'s drawing circle is done. 它应该使用.start()绘制一个圆,而其他.start()不应在正式.start()的绘制圆完成之前开始。

In linked page's package, Ex3_Canvas1 class has main and use Runnable MyThread0 class to draw a circle using basic .start() and .join() and it does perfectly what I want. 在链接页的程序包中,Ex3_Canvas1类具有main并使用Runnable MyThread0类使用基本的.start()和.join()绘制圆,它可以完美实现我想要的功能。

I created NetBean's automatic JFrame class Ex2_CanvasDemo and tried to do the same and failed. 我创建了NetBean的自动JFrame类Ex2_CanvasDemo并尝试执行同样的操作,但失败了。 JFrame window pops up after drawing a full circle and then shows creating of next circle. 绘制一个完整的圆后,将弹出“ JFrame”窗口,然后显示创建下一个圆。 What I want is that the window should first appear and it shows creation of both circles ,not simulataneously but sequently, like Ex3_Canvas1. 我想要的是该窗口应该首先出现,并且它显示了两个圆的创建,而不是同时显示,而是依次显示,例如Ex3_Canvas1。

I guess it's because main thread waits for th(Ex2_CanvasDemo) to finish so window doesn't apply for changes. 我猜这是因为主线程等待th(Ex2_CanvasDemo)完成,所以窗口不适用于更改。 But shouldn't Ex1_Canvas1 should do the same? 但是Ex1_Canvas1不应该这样做吗? Is this differences due to automatically generated code by netbeans? 这种差异是由于netbeans自动生成的代码引起的吗? How can I do the same as Ex1_Canvas1 in Ex2_CanvasDemo. 如何与Ex2_CanvasDemo中的Ex1_Canvas1相同。

I tried making a Runnable class and used in Ex2_CanvasDemo but failed also.. 我尝试制作一个Runnable类并在Ex2_CanvasDemo中使用,但也失败了。

Any help? 有什么帮助吗? I'm using jdk 8 and netbeans8 on mac. 我在Mac上使用jdk 8和netbeans8。

--Thread part of Ex2_CanvasDemo-- -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);
//        }


    }

Caveat 警告

Animation is hard, good animation is really hard. 动画很难,好的动画真的很难。 You need to repeat this to yourself, because animation done right is, really hard. 您需要自己重复一遍,因为正确完成动画非常困难。

What you need to know... 您需要知道的...

Animation is basically the illusion of change over time. 动画基本上是随着时间变化的幻觉。 Very rarely do you want to perform linear animation, animation is normally done over a period of time, as it allows for performance difference in the platform to be smoothed out in away which is not as harsh to the user. 您很少执行线性动画,动画通常需要一段时间才能完成,因为它可以消除平台上的性能差异,这对用户而言并不那么苛刻。

Swing is single threaded and not thread safe. 摆动是单线程的,不是线程安全的。 This means that you should not block the event dispatching thread and that you must only update the UI from within the context of the event dispatching thread. 这意味着您不应该阻塞事件分发线程,而只能从事件分发线程的上下文中更新UI。

See Concurrency in Swing for more details 有关更多详细信息,请参见Swing中的并发。

This makes life a little difficult, as you can't simply run a linear loop in the EDT, as this will block the UI and it's difficult to do it from a Thread because it's a mess of synchronisation. 这给生活带来了一些困难,因为您不能简单地在EDT中运行线性循环,因为这会阻塞UI,并且很难从Thread因为这是一团糟的同步。

One of the simplest solutions is to make use of the available API and use a Swing Timer , which acts as a pseudo loop, putting in a small delay between call backs, in which you can perform some operations 最简单的解决方案之一是利用可用的API并使用Swing Timer ,该Timer充当伪循环,从而在回叫之间间隔一小段时间,您可以在其中执行一些操作

Example... 例...

While there are a number of ways you might approach this, I've set up a simple List which contains a bunch of Animatable s which "do stuff" and then simply run one after the other in serial. 尽管有多种方法可以解决此问题,但我设置了一个简单的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM