简体   繁体   中英

Why I can't add more than one Object to the JPanel?

When I add to the GameScreen more than one Object of class Duck only one appears on the screen. When I add Duck outside constructor in GameScreen class I have many Object of Duck but then the mouseClicked method doesn't work on Duck.

Take a look at How to Use BorderLayout . BorderLayout will only present the last component added to any single position.

Having said that, I don't think this is the direction you really want to head in. Instead, start with a single JPanel and override its paintComponent method, then render all you game objects directly through. Components are heavy objects with a lot of complexity and aren't generally well suited for this kind of operation.

Also, you also don't need 3+ threads (Swing Timer s make use of a thread to schedule calls back to the UI). Use a single Swing Timer as your "main game loop", which should be responsible for updating the state and scheduling paint passes. Swing is not thread safe, so the use of the Thread to update the label is ill advised.

在此处输入图像描述

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.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    BufferedImage img = ImageIO.read(getClass().getResource("/images/Duck.png"));
                    List<Duck> ducks = new ArrayList<>();
                    ducks.add(new Duck(img));
                    ducks.add(new Duck(img));

                    JFrame frame = new JFrame();
                    frame.add(new GamePane(ducks));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public class Duck {
        private BufferedImage image;

        private int x;
        private int y;

        private int xDelta = 0;
        private int yDelta = 0;

        public Duck(BufferedImage image) {
            this.image = image;
        }

        public BufferedImage getImage() {
            return image;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        public void setLocation(int x, int y) {
            setX(x);
            setY(y);
        }

        public void setX(int x) {
            this.x = x;
        }

        public void setY(int y) {
            this.y = y;
        }

        public int getWidth() {
            return image == null ? 0 : image.getWidth();
        }

        public int getHeight() {
            return image == null ? 0 : image.getHeight();
        }

        public void setDelta(int x, int y) {
            xDelta = x;
            yDelta = y;
        }

        public int getXDelta() {
            return xDelta;
        }

        public int getYDelta() {
            return yDelta;
        }

        public void move(Rectangle bounds) {
            int xDelta = getXDelta();
            int yDelta = getYDelta();
            int x = getX() + xDelta;
            int y = getY() + yDelta;

            if (x < bounds.x) {
                x = bounds.x;
                xDelta *= -1;
            } else if (x + getWidth() >= bounds.x + bounds.width) {
                x = (bounds.x + bounds.width) - getWidth();
                xDelta *= -1;
            }

            if (y < bounds.y) {
                y = bounds.y;
                yDelta *= -1;
            } else if (y + getWidth() >= bounds.y + bounds.height) {
                y = (bounds.y + bounds.height) - getHeight();
                yDelta *= -1;
            }
            setDelta(xDelta, yDelta);
            setLocation(x, y);
        }

        public void paint(Graphics2D g2d, ImageObserver observer) {
            g2d.drawImage(getImage(), getX(), getY(), observer);
        }
    }

    public class GamePane extends JPanel {
        private List<Duck> ducks;

        public GamePane(List<Duck> ducks) {
            this.ducks = ducks;

            Random rnd = new Random();

            for (Duck duck : ducks) {
                int width = 400 - duck.getWidth();
                int height = 400 - duck.getHeight();

                int x = rnd.nextInt(width);
                int y = rnd.nextInt(height);

                int xDelta = rnd.nextBoolean() ? 1 : -1;
                int yDelta = rnd.nextBoolean() ? 1 : -1;

                duck.setLocation(x, y);
                duck.setDelta(xDelta, yDelta);
            }

            Timer timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Rectangle bounds = new Rectangle(getSize());
                    for (Duck duck : ducks) {
                        duck.move(bounds);
                    }
                    repaint();
                }
            });
            timer.start();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Duck duck : ducks) {
                Graphics2D g2d = (Graphics2D) g.create();
                duck.paint(g2d, this);
                g2d.dispose();
            }
        }
    }
}

From this, you can start adding more entities as needed, for example, I can modify the Main method to include LOTs of ducks...

BufferedImage img = ImageIO.read(getClass().getResource("/images/Duck.png"));
List<Duck> ducks = new ArrayList<>(100);
for (int index = 0; index < 100; index++) {
    ducks.add(new Duck(img));
}

This is obviously and overly simplified example intended only as a demonstration of core concept, you'll need to do more research into basic game development and 2D graphics.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM