为什么我可以向JPanel添加多个对象?

发布于 2025-01-31 09:44:47 字数 82 浏览 2 评论 0原文

当我添加到游戏屏幕上时,多个鸭子的对象只有一个在屏幕上出现。当我在Games屏幕类中添加鸭外构造函数时,我有许多鸭子对象,但是这种鼠标的方法不起作用。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

美人迟暮 2025-02-07 09:44:47

看看如何使用borderlayout BorderLayout将仅显示添加到任何单个位置的最后一个组件。

话虽如此,我不认为这是您真正想进入的方向。相反,以单个jpanel开始并覆盖其paintcomponent方法,然后渲染全部您直接通过游戏对象。组件是具有很大复杂性的重物,通常不适合这种操作。

另外,您也不需要3个以上的线程(swing 计时器 s使用线程将调用安排回UI)。使用单个秋千计时器作为您的“主游戏循环”,该循环应负责更新状态和调度油漆通过。摆动不是线程安全的,因此建议使用螺纹更新标签。

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();
            }
        }
    }
}

从中,您可以根据需要开始添加更多实体,例如,我可以修改main方法,以包括很多鸭子...

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));
}

显然这是并且过于简化示例仅作为核心概念的演示,您需要对基本游戏开发和2D图形进行更多研究。

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 Timers 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.

enter image description here

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文