我的JPanel实例是否被处理掉(为什么?)

时间:2014-01-21 00:20:21

标签: java swing jpanel paintcomponent

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

这些卡仍然在每个播放器的卡片列表中,但不在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;
    }
}

1 个答案:

答案 0 :(得分:2)

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

顺便说一下,我看到代码中过度使用静态修饰符以及看起来过于复杂的代码,增加了程序的“圈复杂度”,使得难以调试和增强