繁体   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

我想做的是绘制圆,但是一次在画布上绘制一个圆,然后使用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.

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