Creating endless number of objects in JPanel and draw them through PaintComponent in Java

前端 未结 3 2031
别那么骄傲
别那么骄傲 2021-01-20 11:59

I have one dilemma , how to realize application. I have JPanel with width 288 and height 512, then I created two objects ( images ) and drew them through paintComponent usin

3条回答
  •  -上瘾入骨i
    2021-01-20 12:18

    The following solution is based on my previous answer.
    I add it in response to MadProgrammer's comment: "A better solution is to pool the objects for re-use".
    DrawAblesProducer produces drawable objects on-demand. It also stores surplus object, to prevent producing too many such objects.
    I post it as a separate answer because the additional functionality comes with somewhat higher complexity:

    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.io.IOException;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Queue;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class ImageAnimator {
    
        private static final int W = 288, H = 512;
    
        public ImageAnimator() {
            SwingUtilities.invokeLater(() -> {
                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new AnimationPane(new DrawAblesProducer()));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            });
        }
    
        public class AnimationPane extends JPanel {
    
            private final List drawables;
            private static final int CYCLE_TIME = 5;
            private final DrawAblesProducer producer;
    
            public AnimationPane(DrawAblesProducer producer) {
                this.producer = producer;
                drawables = new ArrayList<>(2);
                drawables.add(producer.issue(W, H/4));
                drawables.add(producer.issue(W, 3*H/4));
    
                Timer timer = new Timer(CYCLE_TIME, e ->  animate());
                timer.start();
            }
    
            private void animate() {
    
                for (Drawable drawable : new ArrayList<>(drawables)) {
                    drawable.update();
                    if(drawable.getX() == W/2) {
                        drawables.add(producer.issue(W)); //random Y
                    }else if(drawable.getX() <= 0) {
                        drawables.remove(drawable);
                        producer.retrn(drawable);
                    }
                }
                repaint();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(W, H);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                for (Drawable drawable : drawables ) {
                    g.drawImage(drawable.getImage(),drawable.getX(), drawable.getY(), null);
                }
            }
        }
    
        //produces `drawable` objects on-demand. stores surplus object, to prevent producing 
        //too many such objects
        public class DrawAblesProducer {
    
            private final Queue warehouse = new LinkedList<>();
    
            public Drawable issue(int x){
                return issue(x, -1);
            }
    
            public Drawable issue(int x, int y){
    
                Drawable drawable = warehouse.poll();
                if(drawable != null ) {
                    drawable.setX(x); drawable.setY(y);
                    return  drawable;
                }
                return new Drawable(x, y);
            }
    
            public void retrn(Drawable drawable){
                warehouse.add(drawable);
            }
        }
    
        public static class Drawable {
    
            //made static so image is reused for all instances
            private static final Image image = image();
    
            private int x, y;
    
            //construct with a random y value
            public Drawable(int x) {
                this(x, -1);
            }
    
            public Drawable(int x, int y) {
                setX(x);
                setY(y);
            }
    
            public int getX() { return x;  }
            public void setX(int x) { this.x = x;}
    
            public int getY() { return y; }
            public void setY(int y) {
                this.y = y < 0 ? randomY() : y  ;
            }
    
            private int randomY() {
                int iHeight = image.getHeight(null);
                return iHeight + (int) (Math.random() * (H - iHeight));
            }
    
            public void update() {  x--; }
    
            public Image getImage(){  return image; }
    
            public static Image image() {
    
                URL url = null;
                try {
                    url = new URL("https://dl1.cbsistatic.com/i/r/2017/09/24/b2320b25-27f3-4059-938c-9ee4d4e5cadf/thumbnail/32x32/707de8365496c85e90c975cec8278ff5/iconimg241979.png");
                    return ImageIO.read(url);
    
                } catch ( IOException ex) { ex.printStackTrace();   }
                return null;
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(()->new ImageAnimator());
        }
    }
    

提交回复
热议问题