添加 paint 方法后我的 JPanel 不显示

My JPanel doesn't show after adding the paint method

我最近为我的第一个棋盘游戏创建了我的第一个棋盘,并在我的 JPanel.I 上以多种方式绘制棋盘,最终决定使用标签,但由于我需要向该标签添加图片,我不得不更改它变成 JLabel.The 语法是正确的,但 Jlabels 不显示。 我尝试清理我的绘画方法,它开始显示,但标签的背景没有改变。

我尝试将代码放入我的绘画方法中,但没有成功。 我也尝试在我的绘制方法之后将容器添加到框架中,但它也没有用。

以下是我的代码的一些重要部分:

    ////////////////////////////////////
    //The constructor, Creates the frame.
    ////////////////////////////////////
    public SecondFrame() {
        setTitle("Counter Strike");
        setIconImage(Toolkit.getDefaultToolkit().getImage(SecondFrame.class.getResource("/cs/resources/icon2.png")));

        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(150, 10, WIDTH, HEIGHT);
        contentPane = new JPanel();
        //contentPane.setBackground(Color.CYAN);
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
       
        setContentPane(contentPane);
        GroupLayout gl_contentPane = new GroupLayout(contentPane);
        gl_contentPane.setHorizontalGroup(
            gl_contentPane.createParallelGroup(Alignment.LEADING)
                .addGap(0, 984, Short.MAX_VALUE)
        );
        gl_contentPane.setVerticalGroup(
            gl_contentPane.createParallelGroup(Alignment.LEADING)
                .addGap(0, 662, Short.MAX_VALUE)
        );
        contentPane.setLayout(gl_contentPane);
        
    
        
        

        //Starting the game.
        start();
        
        
        
          //Initializing the label "boardParts" 2D array.
            frame();


    }
    
    
    
    
    
    //////////////////
    //Draws the board
    //////////////////
    
    public void frame() {
        
        boardParts=new JLabel[rows][columns];
        
        for(int i=0;i<rows;i++)
            for(int j=0;j<columns;j++) {
                
                boardParts[i][j]=new JLabel();
                boardParts[i][j].setBounds(100*i+100, 100*j+100, tilesize, tilesize);
                boardParts[i][j].setBorder(new LineBorder(new Color(0, 0, 0)));

                if(randomBarrier()) 
                     boardParts[i][j].setIcon(new ImageIcon(FirstFrame.class.getResource("/cs/resources/boundIcon.png")));
                else
                    boardParts[i][j].setBackground(Color.yellow);
                 contentPane.add(boardParts[i][j]);
                 
            }
        
    }
    
  

我还在我的另一个 classes 中创建了这个 class 的新对象,当我 运行 它显示错误大约 1 秒,然后将它们擦掉所以我不知道这些错误是什么意思。

所以这是我简化的代码:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Toolkit;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.GroupLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.GroupLayout.Alignment;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.event.ActionEvent;

public class Frame1 {

    private JFrame frame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Frame1 window = new Frame1();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public Frame1() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        JButton btnNewButton = new JButton("New button");
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                frame.setVisible(false);
                SecondFrame frame2 = new SecondFrame();
                frame2.setVisible(true);
                
            }
        });
        GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
        groupLayout.setHorizontalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addGap(42)
                    .addComponent(btnNewButton)
                    .addContainerGap(303, Short.MAX_VALUE))
        );
        groupLayout.setVerticalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup()
                    .addContainerGap(183, Short.MAX_VALUE)
                    .addComponent(btnNewButton)
                    .addGap(56))
        );
        frame.getContentPane().setLayout(groupLayout);
    }
}


package hello;

import java.awt.Color;
import java.awt.Toolkit;

import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.GroupLayout.Alignment;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class SecondFrame extends JFrame implements Runnable{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
    private static int WIDTH=1000,HEIGHT=700;
    private static int boardWidth=500,boardHeight=500;  //The width and height of the game board.
    private Thread thread;
    private boolean isRunning;
    private BoardParts barriers;
    private int rows=8,columns=5,tilesize=100;
    private JLabel[][] boardParts;
    private boolean[][] notBarrier;

    
    
    

    ////////////////////
    //Creates the frame.
    ////////////////////
    public SecondFrame() {
        setTitle("Counter Strike");
        setIconImage(Toolkit.getDefaultToolkit().getImage(SecondFrame.class.getResource("/cs/resources/icon2.png")));

        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(150, 10, WIDTH, HEIGHT);
        contentPane = new JPanel();
        contentPane.setBackground(Color.CYAN);
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
       
        setContentPane(contentPane);
        GroupLayout gl_contentPane = new GroupLayout(contentPane);
        gl_contentPane.setHorizontalGroup(
            gl_contentPane.createParallelGroup(Alignment.LEADING)
                .addGap(0, 984, Short.MAX_VALUE)
        );
        gl_contentPane.setVerticalGroup(
            gl_contentPane.createParallelGroup(Alignment.LEADING)
                .addGap(0, 662, Short.MAX_VALUE)
        );
        contentPane.setLayout(gl_contentPane);
        
    
        
        

        //Starting the game.
        start();
        
        
        
        //Initializing the label "boardParts" 2D array.
        frame();
        


    }
    

    
    
    //////////////////
    //Draws the board
    //////////////////
    
    public void frame() {
        
        boardParts=new JLabel[rows][columns];
        notBarrier=new boolean[rows][columns];
        
        for(int i=0;i<rows;i++)
            for(int j=0;j<columns;j++) {
                
                boardParts[i][j]=new JLabel();
                boardParts[i][j].setBounds(100*i+100, 100*j+100, tilesize, tilesize);
                boardParts[i][j].setBorder(new LineBorder(new Color(0, 0, 0)));

                if(randomBarrier()) {
                     boardParts[i][j].setIcon(new ImageIcon(Frame1.class.getResource("/cs/resources/boundIcon.png")));
                     notBarrier[i][j]=false;
                }
                else {
                    boardParts[i][j].setBackground(Color.yellow);
                    notBarrier[i][j]=true;
                }
                 contentPane.add(boardParts[i][j]);
                 
            }
    

    }
    
    


    
    ///////////////////////////////////////////////////////////////////////////
    //finds a random place for the barrier objects in the beginning of the game.
    ///////////////////////////////////////////////////////////////////////////

    public static boolean randomBarrier() {  //Should put all the parts to this method to see if the are barrier material or not.
        
        
        int row = WIDTH/100;
        int column = HEIGHT/100;
        
        int min = 0;
        int max = row*column;
        
        double random = Math.random();
        
        if(random<0.4)
            return true;
        
        else if(random>=0.4)
           return false;
        
        return true;
        
    }


    
    
    
    
    //////////////////
    //Starts the game.
    /////////////////
    public void start() {
        
        isRunning = true;
        thread = new Thread(this);
        thread.start();
        
    }
    
    
    
    
    ////////////////
    //Stops the game.
    ///////////////
    public void stop() {
        
        isRunning = false;
        try {
            thread.join();
        } catch (InterruptedException e) {
            System.out.println("An error occured...");
            e.printStackTrace();
        }
        
    }
    
    
    
    public void tick() {
        
        
    }
    

    
    
    @Override
    public void run() {


        while(isRunning) {
            tick();
            repaint();
        }
        
    }
    
    
}


package hello;

public class BoardParts {

}

我认为,您必须为您的板覆盖 paintComponent(Graphics g)。 您必须将要绘制的所有内容保存在 Collection 中,然后在 paintComponent override 中绘制它们。

  1. post编写代码时不要使用“代码片段”。相反,您粘贴代码,select 代码,然后使用 {} 按钮突出显示代码。

  2. Post posting 代码时的正确 minimal reproducible example。这是直接演示所述问题的最小代码。代码应该在一个文件中,我们应该能够 copy/paste/compile 并测试代码。这样做的目的是迫使您删除所有不必要的代码,以便更容易理解问题。大多数时候你会发现你自己的问题。你被要求做 MRE 是以前的问题。每个问题都应该有一个 MRE,这样我们就不必猜测你在做什么。

  3. 在我看来你有一个二维网格。不要使用 GroupLayout。这告诉我您正在使用 IDE 生成代码。您花时间学习 IDE 而不是学习 Swing。您可以轻松地将 GridLayout 用于二维网格。

  4. 不要使用静态变量。不需要您的宽度、高度、boardWidth 和 boardHeight 变量。每个 Swing 组件都应负责确定自己的首选大小。然后在将所有组件添加到框架后,在使框架可见之前 pack() 框架。然后框架将确定其适当的大小。在这种情况下,您可以对每个 JLabel 使用 setPreferredSize(...) 使它们成为您的图块的大小。因此,在循环之外,您创建了一个 Dimension 对象的单个实例,供所有标签共享。

  5. 不要在 setBounds() 方法中使用幻数。在你上一个问题中,你得到了没有使用幻数的解决方案。事实上,您甚至不应该使用 setBounds() 方法。设置组件的 size/location 是布局管理器的工作。

  6. 不要为动画使用线程。动画应该使用 Swing Timer 来完成。对 Swing 组件的所有更新都应该在事件调度线程 (EDT) 上完成。 Swing Timer 将在 EDT 上执行。

  7. 不要创建 Icon 的多个实例。一个图标可以被多个组件共享。因此,您在循环代码之外创建了一个 Icon 实例,并将该实例用于所有组件。

  8. LineBorder。您只需要一个实例。

  9. 在你上一个问题的评论中,你得到了关于如何使用单个语句编写 randomBarrier() 方法的建议。你post这里的代码是完全没有必要的。甚至没有使用前 4 个语句中的变量。

but the Jlabels do not show.

正如我之前建议的那样,您可以在面板上使用 GridLayout 并将标签添加到面板,将面板添加到框架。阅读 Layout Manager 上的 Swing 教程,了解更多信息和工作示例。

I tried cleaning my paint method

没有理由使用自定义绘制方法。您现在正在使用 Swing 组件 (JLabel),Swing 将为您完成所有绘制工作。另外,正如您在上一个问题中提到的,如果您确实需要进行自定义绘画,您可以覆盖 paintComponent() 方法。我们不应该一直重复同样的建议。

the background of the labels doesn't change.

A JLabel 是唯一默认情况下不透明的 Swing 组件。所以你需要使用:

label.setOpaque( true );

当您创建每个 JLabel 时。