java - 我的 JPanel 实例是否被处置(为什么?)

标签 java swing jpanel paintcomponent

在我的代码中,我的主类创建一个 JFrame,然后实例化一堆 Player 并将它们放入 ArrayList 中。然后它创建一堆卡片(JPanel)并将它们添加到每个玩家的 ArrayList 中。问题是,在完成所有这些之后,JFrame 只有一个卡组件,即使它们都是在 Card 的构造函数中添加到 JFrame 中的。

这些卡牌仍然位于每个玩家的卡牌 ArrayList 中,但不在 JFrame 中。

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JPanel;

public class Uno {

    public static void main(String[] args) {
        Uno g = new Uno(2, 6);
    }
    private ArrayList<Player> players = new ArrayList<Player>();
    public static Uno uno;
    private static GuiUno gui;

    public Uno(int numPlayers, int initialCards) {
        gui = new GuiUno();
        gui.setVisible(true);

        for (int i = 0; i < numPlayers; i++) {
            players.add(new Player(i));
        }
        for (Player p : players) {
            for (int i = 0; i < initialCards; i++) {
                p.drawCard(p.randCard());
            }
        }

    }

    public static GuiUno getGUI() {
        return gui;
    }

    public void addCardToGUI(Card c) {
        gui.add(c);
    }

    public ArrayList<Player> getPlayers() {
        return players;
    }
}

class Card extends JPanel {

    private static Font font;
    private static FontMetrics metrics;
    private int number;
    private Player p;
    private Color color;
    private int x, y;

    public Card(Player p, int number, Color color) {
        if (font == null) {
            this.font = GuiUno.font.deriveFont((float) 12);
        }
        this.number = number;
        this.color = color;
        this.p = p;
        updateCoords();
        Uno.getGUI().add(this);
        System.out.println(color.toString() + " " + number + " " + x + " " + y);
    }

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

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

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

    private String getText() {
        if (number > 0) {
            return String.valueOf(number);
        } else {
            switch (number) {
                case -1:
                    return "Wild";
                case -2:
                    return "+2 Draw";
                case -3:
                    return "Skip";
                case -4:
                    return "Reverse";
                case -5:
                    return "+4 Wild";
            }
        }
        return String.valueOf(number);
    }

    public Color getColor() {
        return color;
    }

    public int getNumber() {
        return number;
    }

    public void updateCoords() {
        int x = 0, y = 0;
        switch (p.POS) {
            //top
            case 0:
                x += 15;
                y += 15;
                x += 50 * p.getHand().size();
                break;
            //bottom
            case 1:
                x += 15;
                y += Uno.getGUI().getContentPane().getHeight() - 15;
                x += 50 * p.getHand().size();
                break;
            //left
            case 2:
                x += 15;
                y += 15;
                y += 77 * p.getHand().size();
                break;
            //right
            case 3:
                x += Uno.getGUI().getContentPane().getWidth() - 15;
                y += 15;
                y += 77 * p.getHand().size();
                break;
        }
        System.out.println("" + x + " " + y);
        this.x = x;
        this.y = y;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        if (metrics == null) {
            metrics = g.getFontMetrics(font);
        }
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.fillRect(x, y, 50, 77);
        g.setColor(Color.WHITE);
        g2.setFont(this.font);

        g2.drawString(getText(), (x + 3), y + 19);
        AffineTransform orig = g2.getTransform();
        g2.rotate(Math.PI, x + 48, y + 66);
        g2.drawString(getText(), (x + 48), y + 66);
        g2.setTransform(orig);

    }
}

class GuiUno extends JFrame {

    public static Font font;
    Container pane;

    public GuiUno() {
        try {
            this.font = Font.createFont(Font.PLAIN, new File("tahoma.ttf"));
        } catch (IOException e) {
            System.out.println("Missing font file tahoma.ttf");
            System.exit(0);
        } catch (Exception e) {

        }
        this.setTitle("Uno");
        this.setSize(500, 500);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

    }
}

class Player {

    private boolean human;
    private ArrayList<Card> hand = new ArrayList<Card>();

    public final int POS;

    public Player(int i) {
        this.POS = i;
    }

    public void drawCard(Card c) {
        hand.add(c);

    }

    public ArrayList<Card> getHand() {
        return hand;
    }

    public Card randCard() {
        Card c = new Card(this, 5, Color.BLACK);
        return c;
    }
}

最佳答案

  • 如果您以默认方式向 JFrame(实际上是其 contentPane)添加多个组件并且未更改布局管理器,则它们将被添加到 BorderLayout.CENTER 位置的使用 BorderLayout 的容器中,因此每添加一个都会覆盖最后一个。解决方案是使用其他布局或 JPanel 和布局的组合。
  • 您希望显示您的玩家在游戏 table 上玩游戏,因此需要弄清楚如何在主 JPanel 中分配您的玩家 JPanel。我不确定您是否希望它们全部排成一排或围绕圆形或规则的几何 table 排列,但这就是您首先必须弄清楚的。
  • 我会首先创建非 GUI 逻辑类,这些类封装了扑克牌、牌组、游戏、玩家背后的逻辑,然后创建相应的 GUI 组件来显示逻辑组件。
  • 我的 Card GUI 不会是 JPanel,而是显示 ImageIcon 的 JLabel。

顺便说一句,我发现您的代码中过度使用了静态修饰符,并且代码看起来过于复杂,增加了程序的“圈复杂度”,使得调试和增强变得困难.

关于java - 我的 JPanel 实例是否被处置(为什么?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21246822/

相关文章:

java - 使用 Apache CXF webclient 时导致此 ClassLoader StackOverflowError 的原因是什么?

java - 循环测验,Java

java - 添加将 JPanel 扩展为 JFrame 的公共(public)类

java - 如何让 GridBagLayout 正确排列

Java 获取 JPanel 组件

java - 如何在java中为带括号的字符串编写正则表达式?

java - 按钮属性不会改变

java - Libgdx 与 Java Swing 问题

java - 是否可以在 JAXX 框架中使用 java 7 语法?

java - 按插入顺序获取选定的JTree节点索引