Java рисование круга с использованием awt, JFrame with Thread (Runnable) в Netbeans (Mac) - PullRequest
0 голосов
/ 16 января 2019

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, чтобы нарисовать круг, используя basic .start () и .join (), и он отлично выполняет то, что я хочу.

Я создал автоматический класс JFrame в NetBean Ex2_CanvasDemo и попытался сделать то же самое, но потерпел неудачу.Окно JFrame появляется после рисования полного круга, а затем показывает создание следующего круга.Я хочу, чтобы сначала появилось окно, и оно показывает создание обоих кругов, не одновременно, а последовательно, как Ex3_Canvas1.

Я полагаю, это потому, что основной поток ожидает завершения th (Ex2_CanvasDemo), поэтому окно не применяется для изменений.Но не должен ли Ex1_Canvas1 делать то же самое?Это связано с тем, что netbeans автоматически генерирует код?Как я могу сделать так же, как Ex1_Canvas1 в Ex2_CanvasDemo.

Я пытался создать класс Runnable и использовал его в Ex2_CanvasDemo, но тоже не получилось ..

Любая помощь?Я использую JDK 8 и NetBeans8 на Mac.

- Часть потока 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);
//        }


    }

1 Ответ

0 голосов
/ 16 января 2019

Протест

Анимация сложная, хорошая анимация действительно сложная. Вы должны повторить это для себя, потому что анимация, сделанная правильно, действительно трудна.

Что нужно знать ...

Анимация - это иллюзия изменений во времени. Очень редко вы хотите выполнять линейную анимацию, обычно анимация выполняется в течение определенного периода времени, поскольку она позволяет сгладить разницу в производительности платформы, что не так резко для пользователя.

Качели однопоточные и не безопасны. Это означает, что вы не должны блокировать поток диспетчеризации событий и обновлять пользовательский интерфейс только в контексте потока диспетчеризации событий.

См. Параллельность в Swing для получения более подробной информации

Это немного усложняет жизнь, поскольку вы не можете просто запустить линейный цикл в EDT, так как это заблокирует пользовательский интерфейс, и это трудно сделать из Thread, потому что это беспорядок синхронизации.

Одним из самых простых решений является использование доступного API и использование Swing 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);
        }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...