java - JPanel 出现在两个位置

标签 java swing layout jframe jpanel

我正在设计一个使用 Java swing 框架的基于网格的游戏。我有一个 JFrame,里面有两个 JPanel,但其中一个出现在两个地方。这是一个截图: enter image description here

标有“Turn 1”并带有按钮的面板应该只出现在网格的右侧,但奇怪的是它也出现在左上角。这是我的代码:

public class ArenaPanel extends JPanel {

    private final GridPanel gp;
    private final InfoPanel ip;
    private GameManager gm;
    private int w, h;
    private int cw, ch;
    private double tw, th;
    private Point p2;
    private Point p1;
    private int shotWidth;
    private Color shotColor;

    public ArenaPanel(int w, int h) {
        Images.load();
        setLayout(new GridBagLayout());
        this.w = w;
        this.h = h;
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 1;
        c.weightx = 0;
        c.weighty = 1;
        gp = new GridPanel();
        gp.setPreferredSize(new Dimension(700, 700));
        this.add(gp, c);
        c.gridx = 1;
        c.weightx = c.weighty = 0;
        ip = new InfoPanel();
        add(ip, c);
    }

    public void setGameManager(GameManager g) {
        gm = g;
    }

    public void start() {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                gm.start();
            }
        });
        t.start();
    }

    public void step() {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                gm.doTurn();
            }
        });
        t.start();
    }

    public void paint(Graphics g) {
        g.setColor(Color.black);
        int val = Math.min(getWidth() - 200, getHeight());
        gp.setPreferredSize(new Dimension(val, val));
        gp.revalidate();
        g.fillRect(0, 0, getWidth(), getHeight());
        paintComponents(g);
    }

    private class GridPanel extends JPanel {

        public void paint(Graphics g) {
            cw = getWidth();
            ch = getHeight();
            g.setColor(Color.gray);
            g.fillRect(0, 0, cw, ch);
            tw = (double) cw / w;
            th = (double) ch / h;
            g.setColor(Color.black);
            for (int i = 0; i < w; i++) {
                g.drawLine((int) (i * tw), 0, (int) (i * tw), ch);
            }
            for (int i = 0; i < h; i++) {
                g.drawLine(0, (int) (i * th), cw, (int) (i * th));
            }
            for (int i = 0; i < w; i++) {
                for (int j = 0; j < h; j++) {
                    Robot t = gm.getGrid()[i][j];
                    if (t != null) {
                        Point p = expand(i, j);
                        g.drawImage(t.getImage(), p.x + t.getOffsetX(),
                                p.y + t.getOffsetY(), (int) tw, (int) th, null);
                    }
                }
            }
            if (p1 != null) {
                Graphics2D g2 = (Graphics2D) g;
                g2.setColor(shotColor);
                g2.setStroke(new BasicStroke(shotWidth));
                g2.drawLine(p1.x, p1.y, p2.x, p2.y);
                p1 = null;
                p2 = null;
            }
        }
    }

    private class InfoPanel extends JPanel implements ActionListener {

        private JButton start, stop, step;
        private JLabel turns;
        private int numTurns = 0;
        private GridBagConstraints gbc;
        private ArrayList<TeamPanel> tpanels;

        public InfoPanel() {
            JPanel buttons = new JPanel();
            setLayout(new GridBagLayout());
            buttons.setLayout(new GridBagLayout());
            gbc = new GridBagConstraints();
            start = new JButton("Start");
            gbc.gridy = 0;
            gbc.gridx = 1;
            turns = new JLabel("Turn 1");
            buttons.add(turns, gbc);
            start.addActionListener(this);
            gbc.gridy = 1;
            gbc.gridx = 0;
            buttons.add(start, gbc);
            step = new JButton("Step");
            step.addActionListener(this);
            gbc.gridx++;
            buttons.add(step, gbc);
            stop = new JButton("Stop");
            stop.addActionListener(this);
            gbc.gridx++;
            buttons.add(stop, gbc);
            gbc.gridx = 0;
            gbc.gridy = 0;
            add(buttons, gbc);
            tpanels = new ArrayList<TeamPanel>();
        }

        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            if (actionEvent.getSource() == start) {
                start();
            } else if (actionEvent.getSource() == stop) {
                gm.stop();
            } else if (actionEvent.getSource() == step) {
                step();
            }
        }

        public void incrementTurn() {
            numTurns++;
            turns.setText("Turn " + numTurns);
        }

        public void initializeTeams(Map<String, TeamInfo> m) {
            Set<String> k = m.keySet();
            for (TeamPanel tp : tpanels) {
                this.remove(tp);
            }
            tpanels.clear();
            gbc.gridy = 1;
            for (String s : k) {
                TeamPanel tp = new TeamPanel(m.get(s));
                add(tp, gbc);
                gbc.gridy++;
                tpanels.add(tp);
            }
            this.revalidate();
        }
    }

    private class TeamPanel extends JPanel {
        private Color col;
        private int score;
        private JLabel scoreLabel;
        private TeamInfo inf;

        public TeamPanel(TeamInfo inf) {
            this.inf = inf;
            col = getColor(inf.c);
            super.setLayout(new FlowLayout());
            BufferedImage ico = new BufferedImage(20, 20, BufferedImage.TYPE_3BYTE_BGR);
            Graphics g = ico.getGraphics();
            g.setColor(col);
            g.fillRect(0, 0, 20, 20);
            add(new JLabel(new ImageIcon(ico)));
            this.add(new JLabel(inf.team));
            scoreLabel = new JLabel("" + inf.score);
            add(scoreLabel);
        }

        public void paint(Graphics g) {
            //g.setColor(col);
            //g.fillRect(-5, 0, 10, 10);
            scoreLabel.setText("Score: " + inf.score);
            this.paintComponents(g);
        }
    }

    public void initializeTeams(Map<String, TeamInfo> m) {
        ip.initializeTeams(m);
    }
}

我在 google 和 StackOverflow 上查找过类似的问题,但找不到。任何帮助将不胜感激。

谢谢!

最佳答案

  • 不要覆盖 paint(...) 方法
  • 改写 JPanel 的 paintComponent(...) 方法。
  • 不要忘记在覆盖中调用 super paintComponent(...) 方法。
  • 并且从不从paint 或paintComponent 方法中调用super 的paintComponents(...)(注意尾随的“s”)。这听起来像是您的问题的原因。

关于java - JPanel 出现在两个位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19818858/

相关文章:

java - 设置 GlassFish 服务器

java - 使用调色板从 TIFF 获取像素颜色索引

java - 需要从用户输入返回值

html - css 嵌套最小高度布局

css - 如何在 css 中制作一个不断增长的列?

Flutter:如何减小 ModalBottomSheet 中 CupertinoPicker 的大小?

java - 重新创建方法调用(使用反射)

java - java中的速记运算符与普通运算符有何不同?

java - 在java中更改特定的文本颜色

java - setImageIcon 不在 mac swing 窗口上设置 JFrame 图标