如何生成多个圆形形状并为框架下方的形状设置动画

单击框架面板时,我无法生成多个椭圆形状。 我想要的是它会产生许多椭圆形状,这些形状会向下移动。 其中一个要求是使用两个multithreading。 但是在我的情况下,我创建的程序是,它只生成一个椭圆形状,并且位置随机变化。 任何人都可以帮我一个。

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安全的,所以让另一个更新UI所依赖的对象状态的Thread需要一些严肃的考虑。 通常,我建议使用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 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 deltas = new HashMap<>(); @Override public void run() { while (true) { try { shapesLock.lock(); try { Rectangle containerBounds = getBounds(); containerBounds.setLocation(0, 0); Iterator 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(); } } }