【问题标题】:Can't move JLabel on JPanel无法在 JPanel 上移动 JLabel
【发布时间】:2015-11-24 00:24:13
【问题描述】:

好的,所以我正在制作一个垄断游戏。到目前为止,我有一个 JFrame,其中一个 JPanel 充当董事会。我已经加载了所有必要的图像。我创建了一个扩展JLabelPlayer 对象,以代表棋盘上的玩家。

我正在尝试在棋盘(JPanel)上设置(希望在棋盘上移动棋子)Player 对象(JLabel)的位置。我试过.setLocation方法,.setBounds方法。

出于某种原因,无论我做什么,Player 对象都只会显示在JPanel 的顶部中间。我想知道如何在我的板上移动Player 对象。

JFrame 代码(我尝试在构造函数底部移动JLabel):

   package com.Game.Monopoly;

    import javax.imageio.ImageIO;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JList;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.Timer;

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.LayoutManager;
    import java.awt.Point;
    import java.awt.SystemColor;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.IOException;

    import net.miginfocom.swing.MigLayout;

    //a class that represent the board (JFrame) and all of it components 
    public class GameFrame extends JFrame {
        private final double SCALE;
        // all the graphical components
        private Board board;
        private JLabel lblPlayerMoney;
        private JLabel lblCurrentPlayer;
        private JLabel lblDice1;
        private JLabel lblDice2;
        private JList lstPropertiesList;
        private JButton btnEndTurn;
        private JButton btnBuyProperty;
        private JButton btnRollDice;

        // all images needed
        private ImageIcon imgDice1;
        private ImageIcon imgDice2;
        private ImageIcon imgDice3;
        private ImageIcon imgDice4;
        private ImageIcon imgDice5;
        private ImageIcon imgDice6;
        private ImageIcon icnAirplane;

        // all players
        private Player[] playerList;
        // all properties
        private Property[] propertiesList;

        public GameFrame(double scale) {
            // SCALE = scale;
            SCALE = 1;

            // set up the JFrame
            setResizable(true);
            setTitle("Monopoly");
            // etUndecorated(true);
            // set size to a scale of 1080p
            setSize((int) (1920 * SCALE), (int) (1080 * SCALE));
            setLayout(new MigLayout());
            loadImages();

            // add the components to the frame
            board = new Board(SCALE);
            board.setPreferredSize(new Dimension((int) (1024 * SCALE),
                    (int) (1024 * SCALE)));
            board.setBackground(Color.BLACK);
            add(board, "east, gapbefore 80");
            lblCurrentPlayer = new JLabel("Current Player:" + " Player 1");
            add(lblCurrentPlayer, "wrap");
            lblPlayerMoney = new JLabel("Player1's money:" + "$14000000");
            add(lblPlayerMoney, "wrap");
            lstPropertiesList = new JList();
            add(new JScrollPane(lstPropertiesList),
                    "span 2 2, grow, height 70:120:200");
            btnRollDice = new JButton("Roll Dice");
            add(btnRollDice, "wrap");
            lblDice1 = new JLabel(imgDice1);
            add(lblDice1);
            lblDice2 = new JLabel(imgDice1);
            add(lblDice2, "wrap");
            btnBuyProperty = new JButton("Buy Property");
            add(btnBuyProperty, "wrap, top");
            btnEndTurn = new JButton("End Turn");
            add(btnEndTurn, "aligny bottom");

            setUpEventListeners();
            loadProperties();

            // load players
            playerList = new Player[6];
            playerList[0] = new Player("Player 1", icnAirplane);

            // add Players to the board

            board.add(playerList[0]);
            playerList[0].setLocation(new Point(500, 230));
        }

        public static void main(String[] args) {
            GameFrame board = new GameFrame(1);
            board.setVisible(true);

        }

        // method to add event listeners
        public void setUpEventListeners() {

            // roll dice
            btnRollDice.addActionListener(new ActionListener() {
                // creates an object with an timers to help with rolling dice
                class RollDice implements ActionListener {
                    private Timer time = new Timer(152, this);
                    private int count = 0;

                    public void actionPerformed(ActionEvent e) {
                        count++;
                        if (count == 21)
                            time.stop();

                        int whatDice1 = (int) (Math.random() * 6) + 1;
                        int whatDice2 = (int) (Math.random() * 6) + 1;

                        // set the icons of the labels according to the random
                        // number

                        if (whatDice1 == 1)
                            lblDice1.setIcon(imgDice1);
                        else if (whatDice1 == 2)
                            lblDice1.setIcon(imgDice2);
                        else if (whatDice1 == 3)
                            lblDice1.setIcon(imgDice3);
                        else if (whatDice1 == 4)
                            lblDice1.setIcon(imgDice4);
                        else if (whatDice1 == 5)
                            lblDice1.setIcon(imgDice5);
                        else if (whatDice1 == 6)
                            lblDice1.setIcon(imgDice6);

                        if (whatDice2 == 1)
                            lblDice2.setIcon(imgDice1);
                        else if (whatDice2 == 2)
                            lblDice2.setIcon(imgDice2);
                        else if (whatDice2 == 3)
                            lblDice2.setIcon(imgDice3);
                        else if (whatDice2 == 4)
                            lblDice2.setIcon(imgDice4);
                        else if (whatDice2 == 5)
                            lblDice2.setIcon(imgDice5);
                        else if (whatDice2 == 6)
                            lblDice2.setIcon(imgDice6);
                    }

                    public void roll() {
                        count = 0;
                        time.start();
                    }
                }

                // create a new dice roll object
                RollDice roll = new RollDice();

                // if the roll dice button is clicked
                public void actionPerformed(ActionEvent arg0) {
                    roll.roll();
                }

            });

        }

        // load all images to memory
        public void loadImages() {
            BufferedImage i = null;
            try {
                i = ImageIO.read((getClass().getResource("/resources/Dice 1.png")));
                imgDice1 = new ImageIcon(i.getScaledInstance(100, 100,
                        java.awt.Image.SCALE_SMOOTH));

                i = ImageIO.read((getClass().getResource("/resources/Dice 2.png")));
                imgDice2 = new ImageIcon(i.getScaledInstance(100, 100,
                        java.awt.Image.SCALE_SMOOTH));

                i = ImageIO.read((getClass().getResource("/resources/Dice 3.png")));
                imgDice3 = new ImageIcon(i.getScaledInstance(100, 100,
                        java.awt.Image.SCALE_SMOOTH));

                i = ImageIO.read((getClass().getResource("/resources/Dice 4.png")));
                imgDice4 = new ImageIcon(i.getScaledInstance(100, 100,
                        java.awt.Image.SCALE_SMOOTH));

                i = ImageIO.read((getClass().getResource("/resources/Dice 5.png")));
                imgDice5 = new ImageIcon(i.getScaledInstance(100, 100,
                        java.awt.Image.SCALE_SMOOTH));

                i = ImageIO.read((getClass().getResource("/resources/Dice 6.png")));
                imgDice6 = new ImageIcon(i.getScaledInstance(100, 100,
                        java.awt.Image.SCALE_SMOOTH));

                i = ImageIO.read((getClass()
                        .getResource("/resources/Airplane Icon.png")));
                icnAirplane = new ImageIcon(i.getScaledInstance(40, 40,
                        java.awt.Image.SCALE_SMOOTH));

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

        // load all properties
        public void loadProperties() {
            propertiesList = new Property[40];

            // set up the properties list
            // (name, index, isBuyable, price, initial rent)
            propertiesList[0] = new Property("Go", 0, false, 0, 0);
            propertiesList[1] = new Property("Jacob's Field", 1, true, 600000,
                    20000);
            propertiesList[2] = new Property("Community Chest", 2, false, 0, 0);
            propertiesList[3] = new Property("Texas Stadium", 3, true, 600000,
                    40000);
            propertiesList[4] = new Property("Income Tax", 4, false, 0, 0);
            propertiesList[5] = new Property("O'Hare International Airport", 5,
                    true, 2000000, 250000);
            propertiesList[6] = new Property("Grand Ole Opry", 6, true, 1000000,
                    60000);
            propertiesList[7] = new Property("Chance", 7, false, 0, 0);

        }
    }

JPanel代码:

package com.Game.Monopoly;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class Board extends JPanel {
    private static final long serialVersionUID = 1L;
    private Image board;

    public Board(double scale) {
        this.setPreferredSize(new Dimension((int) (1024 * scale),
                (int) (1024 * scale)));

        BufferedImage i = null;
        try {
            i = ImageIO.read((getClass().getResource("/resources/monopoly-board-web.jpg")));

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        board = i.getScaledInstance((int) (1024 * scale), (int) (1024 * scale), java.awt.Image.SCALE_SMOOTH);

    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(board, 0, 0, this);
    }

}

Player对象代码:

package com.Game.Monopoly;

import javax.swing.ImageIcon;
import javax.swing.JLabel;

//a class representing a player with its graphical component 
public class Player extends JLabel {

    private String playerName;
    private int money;
    private Property[] propertiesOwned;

    public Player(String n, ImageIcon icon) {
        playerName = n;
        this.setIcon(icon);
    }

    // changes the amount of money available 
    public void changeMoney(int amount) {
        money = money + amount;
    }

    public void movePlayer(int x, int y){ 
        this.setLocation(x, y);
    }

}

【问题讨论】:

  • 您正在与布局管理器作斗争,我相信它默认使用FlowLayout。在这种情况下,您最好设计自己的布局管理器,它支持您的Board,并允许您在虚拟坐标(例如单元格或“游戏位置”)中指定组件的位置,然后将其翻译由布局管理器到现实世界坐标

标签: java swing layout


【解决方案1】:

有几种方法可以实现这一点,就个人而言,最简单的方法是直接使用自定义绘制,而不必为玩家使用基于 Swing 的组件。

您遇到的基本问题是JPanel 默认使用FlowLayout,这意味着您将始终与布局管理器作斗争。在这种情况下,您可以考虑使用自定义布局管理器,例如...

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager2;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Monopoly {

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

    public Monopoly() {
        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 MonopolyBoard());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MonopolyBoard extends JPanel {

        private List<JLabel> players;

        public MonopolyBoard() {
            setLayout(new MonopolyBoardLayout());

            players = new ArrayList<>(2);
            try {
                players.add(makePlayer("/Dog.png"));
                players.add(makePlayer("/Car.png"));

                for (JLabel player : players) {
                    add(player, new Integer(0));
                }
            } catch (IOException exp) {
                exp.printStackTrace();
            }

            Timer timer = new Timer(1000, new ActionListener() {
                private int count = 0;
                private Random rnd = new Random();

                @Override
                public void actionPerformed(ActionEvent e) {
                    int playerIndex = count % players.size();
                    JLabel player = players.get(playerIndex);

                    MonopolyBoardLayout layout = (MonopolyBoardLayout) getLayout();
                    int position = layout.getPosition(player);

                    position += rnd.nextInt(5) + 1;
                    if (position > 35) {
                        position -= 35;
                    }

                    layout.setPosition(player, position);

                    revalidate();
                    repaint();
                    count++;
                }
            });
            timer.start();
        }

        protected JLabel makePlayer(String path) throws IOException {
            JLabel label = new JLabel(new ImageIcon(ImageIO.read(getClass().getResource(path))), JLabel.CENTER);
            return label;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int width = getWidth();
            int height = getHeight();

            for (int index = 0; index < 36; index++) {
                Rectangle bounds = MonopolyBoardLayoutHelper.getCellBounds(index, width, height);
                g2d.draw(bounds);
            }

            g2d.dispose();
        }

    }

    public static class MonopolyBoardLayoutHelper {

        private static Map<Integer, Point> mapBoardCells;

        static {
            mapBoardCells = new HashMap<>(25);

            mapBoardCells.put(10, new Point(0, 8));
            mapBoardCells.put(11, new Point(0, 7));
            mapBoardCells.put(12, new Point(0, 6));
            mapBoardCells.put(13, new Point(0, 5));
            mapBoardCells.put(14, new Point(0, 4));
            mapBoardCells.put(15, new Point(0, 3));
            mapBoardCells.put(16, new Point(0, 2));
            mapBoardCells.put(17, new Point(0, 1));
            mapBoardCells.put(18, new Point(0, 0));

            mapBoardCells.put(0, new Point(9, 9));
            mapBoardCells.put(1, new Point(8, 9));
            mapBoardCells.put(2, new Point(7, 9));
            mapBoardCells.put(3, new Point(6, 9));
            mapBoardCells.put(4, new Point(5, 9));
            mapBoardCells.put(5, new Point(4, 9));
            mapBoardCells.put(6, new Point(3, 9));
            mapBoardCells.put(7, new Point(2, 9));
            mapBoardCells.put(8, new Point(1, 9));
            mapBoardCells.put(9, new Point(0, 9));

            mapBoardCells.put(19, new Point(1, 0));
            mapBoardCells.put(20, new Point(2, 0));
            mapBoardCells.put(21, new Point(3, 0));
            mapBoardCells.put(22, new Point(4, 0));
            mapBoardCells.put(23, new Point(5, 0));
            mapBoardCells.put(24, new Point(6, 0));
            mapBoardCells.put(25, new Point(7, 0));
            mapBoardCells.put(26, new Point(8, 0));
            mapBoardCells.put(27, new Point(9, 0));

            mapBoardCells.put(28, new Point(9, 1));
            mapBoardCells.put(29, new Point(9, 2));
            mapBoardCells.put(30, new Point(9, 3));
            mapBoardCells.put(31, new Point(9, 4));
            mapBoardCells.put(32, new Point(9, 5));
            mapBoardCells.put(33, new Point(9, 6));
            mapBoardCells.put(34, new Point(9, 7));
            mapBoardCells.put(35, new Point(9, 8));

        }

        public static Rectangle getCellBounds(int index, int width, int height) {
            Rectangle bounds = new Rectangle(0, 0, 0, 0);
            int size = Math.min(width, height);
            int cellSize = size / 10;

            int xOffset = (width - size) / 2;
            int yOffset = (height - size) / 2;

            Point point = mapBoardCells.get(index);
            if (point != null) {

                int x = xOffset + (point.x * cellSize);
                int y = yOffset + (point.y * cellSize);
                bounds = new Rectangle(x, y, cellSize, cellSize);

            }

            return bounds;

        }

    }

    public static class MonopolyBoardLayout implements LayoutManager2 {

        public static final int DEFAULT_CELL_SIZE = 64;

        private Map<Component, Integer> cellConstraints;

        public MonopolyBoardLayout() {
            cellConstraints = new HashMap<>(5);
        }

        public Integer getPosition(Component comp) {
            return cellConstraints.get(comp);
        }

        public void setPosition(Component comp, int position) {
            cellConstraints.put(comp, position);
        }

        @Override
        public void addLayoutComponent(Component comp, Object constraints) {
            if (constraints instanceof Integer) {
                int cell = (int) constraints;
                if (cell >= 0 && cell <= 35) {
                    cellConstraints.put(comp, cell);
                } else {
                    throw new IllegalArgumentException(constraints + " is not within the bounds of a valid cell reference (0-35)");
                }
            } else {
                throw new IllegalArgumentException(constraints + " is not a valid cell reference (integer within 0-35)");
            }
        }

        @Override
        public Dimension maximumLayoutSize(Container target) {
            return new Dimension(DEFAULT_CELL_SIZE * 10, DEFAULT_CELL_SIZE * 10);
        }

        @Override
        public float getLayoutAlignmentX(Container target) {
            return 0.5f;
        }

        @Override
        public float getLayoutAlignmentY(Container target) {
            return 0.5f;
        }

        @Override
        public void invalidateLayout(Container target) {
        }

        @Override
        public void addLayoutComponent(String name, Component comp) {
        }

        @Override
        public void removeLayoutComponent(Component comp) {
            cellConstraints.remove(comp);
        }

        @Override
        public Dimension preferredLayoutSize(Container parent) {
            return new Dimension(DEFAULT_CELL_SIZE * 10, DEFAULT_CELL_SIZE * 10);
        }

        @Override
        public Dimension minimumLayoutSize(Container parent) {
            return new Dimension(DEFAULT_CELL_SIZE * 10, DEFAULT_CELL_SIZE * 10);
        }

        @Override
        public void layoutContainer(Container parent) {
            int width = parent.getWidth();
            int height = parent.getHeight();

            Map<Integer, List<Component>> components = new HashMap<>(25);

            for (Component child : parent.getComponents()) {
                Integer cell = cellConstraints.get(child);
                if (cell != null) {
                    List<Component> children = components.get(cell);
                    if (children == null) {
                        children = new ArrayList<>(4);
                        components.put(cell, children);
                    }
                    children.add(child);
                } else {
                    child.setBounds(0, 0, 0, 0);
                }
            }

            for (Map.Entry<Integer, List<Component>> entry : components.entrySet()) {
                int index = entry.getKey();
                Rectangle bounds = MonopolyBoardLayoutHelper.getCellBounds(index, width, height);
                List<Component> comp = entry.getValue();
                int xDelta = 0;
                int yDelta = 0;
                int availableWidth = bounds.width;
                int availableHeight = bounds.height;
                switch (comp.size()) {
                    case 2:
                        availableWidth /= 2;
                        xDelta = availableWidth;
                        break;
                    case 3:
                    case 4:
                        availableWidth /= 2;
                        xDelta = availableWidth;
                        availableHeight /= 2;
                        yDelta = availableHeight;
                        break;
                }
                int x = bounds.x;
                int y = bounds.y;
                for (int count = 0; count < comp.size() && count < 4; count++) {
                    Component child = comp.get(count);
                    child.setSize(availableWidth, availableHeight);
                    child.setLocation(x, y);

                    x += xDelta;
                    if (x >= bounds.x + bounds.width) {
                        x = bounds.x;
                        y += yDelta;
                    }
                }
            }

        }

    }

}

如您所见,这很快就变得非常复杂。这个例子目前每个单元只允许 4 个玩家,所以如果你想要更多,那么你将不得不创建自己的算法

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-12
    • 2019-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    相关资源
    最近更新 更多