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

时间:2016-03-07 06:48:06

标签: 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);
                }
            }           
        }       
    }   
}

1 个答案:

答案 0 :(得分:4)

让我们开始吧,Swing不是Thread安全的,所以让另一个Timer更新UI所依赖的对象状态需要一些严肃的考虑。通常情况下,我建议使用Swing SwingWorkerList来完成此操作,但这些并不是"要求"

为了渲染多个对象,您需要一些方法来存储它们,这样您就可以更新它们的状态并对它们进行渲染。最简单的解决方案是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(); } } } ,您可以查看Collections Trail了解更多详情。

DropBalls

现在,如果你还需要管理颜色,你可以看看我如何管理每个形状的增量,并且应该给你一个想法

    ViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {

    }

    @Override
    public void onPageScrollStateChanged(int state) {
    if (i == 0) {
      ImageView.setBackgroundResource(R.drawable.image1);
    }
    else if (i ==1) {
      ImageView.setBackgroundResource(R.drawable.image2);
    }
    }
});