java - 如何生成多个圆形并使这些形状沿着框架向下移动

标签 java multithreading swing awt

单击框架的面板时,我无法生成多个椭圆形。我想要的是它会生成许多椭圆形并且这些形状会向下移动。要求之一是使用两个多线程。然而,在我的例子中,我创建的程序是,它只会生成一个椭圆形,并且位置是随机变化的。谁能帮我解决这个问题。

package ovalrandomcolors;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.List;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class OvalRandomColors extends JPanel{

    private int ovalX = 50;
    private int ovalY =50;
    private int ovalPositionX = 250;
    private int ovalPositionY = 250;
    private Color color = Color.YELLOW;

    public OvalRandomColors(){
        setBackground(Color.DARK_GRAY);
    }
    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);


        g.setColor(color);
        g.fillOval(ovalPositionX, ovalPositionY, ovalX, ovalY);

        g.setColor(color);
        g.fillOval(ovalPositionX, ovalPositionY, ovalX, ovalY);

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){

            @Override
            public void run() {
               JFrame frame = new JFrame();
               final OvalRandomColors oval = new OvalRandomColors();
               oval.addMouseListener(new MouseAdapter(){
                   @Override
                   public void mouseClicked(MouseEvent e){
                       OvalWithThreading firstThread = new OvalWithThreading(oval);
                       OvalWithThreading secondThread = new OvalWithThreading(oval);

                       Thread first = new Thread(firstThread);
                       Thread second = new Thread(secondThread);
                       second.start();
                       first.start();
                   }
               });

               frame.add(oval);
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               frame.setSize(500,700);
               frame.setVisible(true);
            }  
        });      
    }


    public void updateOval(){

        int r = (int)(Math.random() * 255);
        int g = (int) (Math.random() * 255);
        int b = (int)(Math.random() * 255);

        color = new Color(r,g,b);

        ovalPositionX = (int)(Math.random() * 78);
        ovalPositionY = (int) (Math.random() * 245);

        animateOval();
        repaint();
    }
    public void animateOval(){
           // ovalPositionX += 30;
            ovalPositionY += 30;
    }

    public static class OvalWithThreading implements Runnable{

        private final OvalRandomColors ovalShape;
        public OvalWithThreading(OvalRandomColors oS){
            this.ovalShape = oS;
        }
        @Override
        public void run() {
            for(;;){
                    ovalShape.updateOval();
                try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(OvalRandomColors.class.getName()).log(Level.SEVERE, null, ex);
                }
            }           
        }       
    }   
}

最佳答案

让我们开始吧,Swing 不是 Thread 安全的,因此拥有另一个 Thread 来更新 UI 依赖于呈现的对象的状态需要一些认真的考虑。通常,我建议使用 Swing TimerSwingWorker 来完成此操作,但这些不是“要求”

为了渲染多个对象,您需要一些方法来存储它们,以便您可以更新它们的状态并渲染它们。最简单的解决方案是一个List,你可以看到Collections Trail了解更多详情。

DropBalls

现在,如果您还需要管理颜色,您可以看看我是如何管理每个形状的增量的,应该会给您一个这样做的想法

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JFrame;
import javax.swing.JPanel;
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();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private ReentrantLock shapesLock = new ReentrantLock();
        private List<Ellipse2D> shapes;

        public TestPane() {
            shapes = new ArrayList<>(25);
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    shapesLock.lock();
                    try {
                        shapes.add(new Ellipse2D.Double(e.getX() - 5, e.getY() - 5, 10, 10));
                    } finally {
                        shapesLock.unlock();
                    }
                }
            });

            Thread t = new Thread(new Runnable() {
                private Map<Shape, Double> deltas = new HashMap<>();

                @Override
                public void run() {
                    while (true) {
                        try {
                            shapesLock.lock();
                            try {
                                Rectangle containerBounds = getBounds();
                                containerBounds.setLocation(0, 0);
                                Iterator<Ellipse2D> it = shapes.iterator();
                                while (it.hasNext()) {
                                    Ellipse2D shape = it.next();
                                    Rectangle2D bounds = shape.getBounds2D();
                                    double y = bounds.getY();
                                    Double delta = deltas.get(shape);
                                    if (delta == null) {
                                        delta = 0d;
                                    }
                                    y += delta;
                                    shape.setFrame(bounds.getX(), y, bounds.getWidth(), bounds.getHeight());
                                    if (containerBounds.contains(shape.getBounds())) {
                                        delta = Math.min(delta + 0.25, 6d);
                                        deltas.put(shape, delta);
                                    } else {
                                        it.remove();
                                    }
                                }
                            } finally {
                                shapesLock.unlock();
                            }
                            repaint();
                            Thread.sleep(40);
                        }   catch (InterruptedException ex) {
                        }
                    }
                }
            });
            t.setDaemon(false);
            t.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            shapesLock.lock();
            try {
                for (Ellipse2D shape : shapes) {
                    g2d.fill(shape);
                }
            } finally {
                shapesLock.unlock();
            }
            g2d.dispose();
        }

    }

}

关于java - 如何生成多个圆形并使这些形状沿着框架向下移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35837747/

相关文章:

Java Swing 文件选择器错误

java - 无法在 java Swing 中创建登录表单

java - 从 Hibernate 生成 SQL 脚本

java - EWS API 使用 oAuth2 访问 Office365

java - j2me 网络、线程和死锁

android - 在一个线程上关闭 SQLite 数据库会破坏在另一个线程上打开的数据库

java - 如何使列表线程安全以进行序列化?

java - 无法从java向bash脚本发送参数

java - 使用 lambda 表达式时在变量中存储一些值

Java 错误堆栈跟踪累积