无法将组件添加到扩展 JFrame 的类

Posted

技术标签:

【中文标题】无法将组件添加到扩展 JFrame 的类【英文标题】:Can't add components to a class that extends JFrame 【发布时间】:2012-11-21 13:15:31 【问题描述】:

我正在尝试编写人生游戏。但是,无论我多么努力,我似乎​​都无法使用按钮将 Cell 组件添加到框架上。如果我制作一个新框架并添加它们,它们确实会出现,但即便如此,我似乎无法添加多个组件。

那么我如何将组件添加到框架上,以及如何添加多个组件? 谢谢!

这是我的代码:

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class Visuals extends JFrame implements ActionListener 

    private static Board b;
    private GameOfLife g;
    private JButton nextGen;
    private JButton random;

    public Visuals(Board b)
        super("The Game of Life");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        JPanel panel=new JPanel();
        nextGen = new JButton("Next Generation");
        panel.add(nextGen);
        nextGen.addActionListener(this);

        random = new JButton("Random");
        panel.add(random);
        random.addActionListener(this);
        this.add(panel);

        this.setSize(800, 700);
        this.setVisible(true);


        /*for(int i=0, yShift=80; i<b.getRow(); i++, yShift+=20)
            for (int j=0, xShift=30; j<b.getCol(); j++, xShift+=20)
                Cell c= new Cell(xShift,yShift,i,j);
                this.add(c);
            
        */
        Cell c= new Cell(100,100,1,1);
        Cell d= new Cell(200,200,1,1);
        this.add(c);
        this.add(d);

        JFrame frame=new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 700);
        frame.setVisible(true);

        frame.add(c);
        frame.add(d);

    

    public void paint(Graphics g)
        super.paint(g);
        for(int i=0, yShift=80; i<b.getRow(); i++, yShift+=20)
            for (int j=0, xShift=30; j<b.getCol(); j++, xShift+=20)    
                if(b.getSpot(i, j)==1)
                    g.setColor(Color.red);
                    g.fillRect(xShift, yShift, 10, 10);
                
                else
                    g.setColor(Color.white);
                    g.fillRect(xShift, yShift, 10, 10);
                
               
        
       

    public static void main(String[] cnbe)
        b= new Board (30,30);
        Visuals v = new Visuals(b);
    

    public void actionPerformed(ActionEvent event) 
        Object cause = event.getSource();
        if(cause == nextGen)
            GameOfLife g=new GameOfLife(b);
            g.nextGeneration();
            System.out.println(g);
            this.repaint();
        
        if(cause == random)
            GameOfLife g=new GameOfLife(b);
            g.random();
            System.out.println(g);
            this.repaint();
           
    

    public class Cell extends JComponent
        int row;
        int col;
        int x;
        int y;
        Rectangle r;

        public Cell(int x, int y, int row, int col)
            r= new Rectangle(x,y,10,10);
                this.row=row;
                this.col=col;
                this.x=x;
                this.y=y;

           


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

            g.drawString("DRAW ME",200,200);
            Graphics2D g2= (Graphics2D) g;
            g2.setColor(Color.green);
            r= new Rectangle(x,y,100,100);
            g2.fill(r);

            /*if(b.getSpot(row, col)==1)

                g.setColor(Color.red);
                g.fillRect(x, y, 10, 10);
            
            else

                g.setColor(Color.white);
                g.fillRect(x, y, 10, 10);
            */
        

        class MousePressListener implements MouseListener

            public void mousePressed(MouseEvent event) 
                /*int x= event.getX();
                int y= event.getY();
                if(x>r.getX() && x<r.getX()+10 && y>r.getY() && y<r.getY()+10)
                    if(b.getSpot(row, col)==1)
                        b.setSpot(row, col, 0);
                        repaint();
                    
                    else
                        b.setSpot(row, col, 1);
                        repaint();
                    
                */
            

            public void mouseReleased(MouseEvent arg0) 
            
            public void mouseClicked(MouseEvent arg0) 
            
            public void mouseEntered(MouseEvent arg0) 
            
            public void mouseExited(MouseEvent arg0) 
            

        


    


【问题讨论】:

您与框架布局管理器有冲突。默认情况下,JFrame 将使用BorderLayout,每次您向框架添加新组件时,它都会替换您之前添加的内容(到中心位置)。看看A Visual Guide to Layout Managers 和Using Layout Managers。 另外,一个组件只能属于一个容器,所以当您将单元格添加到第一帧然后添加到第二帧时,它们将从第一帧开始删除 为什么这段代码使用了不止一帧?见The Use of Multiple JFrames, Good/Bad Practice? 【参考方案1】:

您对布局管理器有疑问。每次向 JFrame 添加组件时,都会覆盖已经存在的内容。我对 Game of Life 不太熟悉,但我认为您不希望您的单元格成为 JComponents。您可以将您的板表示为一个布尔数组,表示活动和死亡状态,因此您的 Visual 构造函数变为:

public Visuals(Board b) 
    super("The Game of Life");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Container container = getContentPane(); // 1
    JPanel panel = new JPanel(new FlowLayout()); // 2
    nextGen = new JButton("Next Generation");
    panel.add(nextGen);
    nextGen.addActionListener(this);

    random = new JButton("Random");
    panel.add(random);
    random.addActionListener(this);
    container.add(panel); // 3

    setSize(800, 700);
    setVisible(true);


在您的 Board 类中,您可以将板表示为一个数组:

public class Board
    private boolean[][] board;

    public Board(int x, int y) 

        board = new boolean[x][y];
    

然后在您的 GameOfLife 类的 nextGeneration 方法中,执行您正在执行的任何计算并设置棋盘上位置的真/假(或活/死)状态。

你的 Visuals.paint 方法会变成这样:

public void paint(Graphics g) 
    super.paint(g);
    for (int i = 0, yShift = 80; i < b.getRow(); i++, yShift += 20) 
        for (int j = 0, xShift = 30; j < b.getCol(); j++, xShift += 20) 
            if (b.isAlive(i, j)) 
                g.setColor(Color.red);
                g.fillRect(xShift, yShift, 10, 10);
             else 
                g.setColor(Color.white);
                g.fillRect(xShift, yShift, 10, 10);
            
        
    

iaAlive 只是返回该位置的板数组的值:

public boolean isAlive(int i, int j) 
    return board[i][j];

但就像我说的,我不熟悉这个游戏。

【讨论】:

谢谢大家,我用 GridLayout 解决了我的问题,所以我什至不必担心我的组件的 x 和 y。顺便说一句,罗伯特,我使用 JComponents 向它们添加鼠标列表。

以上是关于无法将组件添加到扩展 JFrame 的类的主要内容,如果未能解决你的问题,请参考以下文章

如何在已经扩展 Thread 的类中扩展 JFrame

JFrame 中的所有组件均未显示

将 JTextArea 添加到 JFrame

将单独类中的多个组件添加到另一个类中的 JFrame

为什么我的JButton在放入JPanel的构造函数时不显示?

AS3 将图像添加到扩展 MovieClip 的类