Can't move JLabel on JPanel

后端 未结 1 1525
野的像风
野的像风 2020-12-22 11:42

Ok, so I am making a monopoly game. I so far have a JFrame, with a JPanel acting as a board. I have loaded all necessary images. I create a P

相关标签:
1条回答
  • 2020-12-22 12:03

    There are a couple of ways you can achieve this, personally, the simplest would be to use custom painting directly and not bother with using Swing based components for the players.

    The basic problem you have is JPanel uses a FlowLayout by default, which means that you will always be fighting layout manager. In this case you might consider using a custom layout manager, for example...

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

    As you can see, this becomes real complicated real quick. This example currently only allows 4 players per cell, so if you want more, then you're going to have to create your own algorithim

    0 讨论(0)
提交回复
热议问题