英文:
My JPanel doesn't show after adding the paint method
问题
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; //游戏板的宽度和高度。
private Thread thread;
private boolean isRunning;
private BoardParts barriers;
private int rows=8,columns=5,tilesize=100;
private JLabel[][] boardParts;
private boolean[][] notBarrier;
////////////////////
//创建框架。
////////////////////
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);
//开始游戏。
start();
//初始化“boardParts” 2D 数组。
frame();
}
//////////////////
//绘制游戏板
////////////////
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]);
}
}
///////////////////////////////////////////////////////////////////////////
//在游戏开始时找到一个随机位置放置障碍物对象。
///////////////////////////////////////////////////////////////////////////
public static boolean randomBarrier() {
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;
}
//开始游戏。
public void start() {
isRunning = true;
thread = new Thread(this);
thread.start();
}
//停止游戏。
public void stop() {
isRunning = false;
try {
thread.join();
} catch (InterruptedException e) {
System.out.println("An error occurred...");
e.printStackTrace();
}
}
public void tick() {
}
@Override
public void run() {
while(isRunning) {
tick();
repaint();
}
}
}
英文:
I recently created my first board for my first board game and draw the board multiple ways on my JPanel.I finally decided to use Label, but since I needed to add pictures to that label, I had to change it into JLabel.The syntax is correct, but the Jlabels do not show.
I tried cleaning my paint method and It started to show,but the background of the labels doesn't change.
I tried putting the code inside my paint method and It didn't work.
I also tried adding the container to the frame after my draw method and it didn't work either.
Here are some essential parts of my code:
////////////////////////////////////
//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]);
}
}
I also create a new object of this class in another one of my classes and when I run it It shows errors for like 1sec and then wipes them off so I don't know what those errors are for.
So this is my reduced code:
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 {
}
答案1
得分: 2
-
在发布代码时,请不要使用 "Code Snippet"。相反,您将代码粘贴到文本中,然后选择代码,然后使用
{}
按钮来突出显示代码。 -
在发布代码时,请提供一个适当的最小可复现示例。这是能够直接演示所述问题的最小代码。代码应该在一个单独的文件中,我们应该能够复制/粘贴/编译和测试代码。这样做的目的是强制您消除所有不必要的代码,以便更容易理解问题。大多数情况下,您会发现自己的问题。您以前被要求提供了一个 MRE。每个问题都应该有一个 MRE,这样我们就不必猜测您在做什么。
-
看起来您有一个二维网格。不要使用 GroupLayout。这告诉我您正在使用IDE生成代码。您正在花时间学习IDE,而不是学习Swing。您可以轻松地为二维网格使用
GridLayout
。 -
不要使用静态变量。您的 width、height、boardWidth 和 boardHeight 变量是不需要的。每个 Swing 组件应负责确定其自己的首选大小。然后在所有组件添加到框架之后,在使其可见之前,对框架进行 pack()。然后框架将确定其适当的大小。在这种情况下,您可以为每个 JLabel 使用 setPreferredSize(...) 使它们的大小与您的 tile 大小相同。因此,在循环之外,您创建一个
Dimension
对象的单个实例,以供所有标签共享。 -
不要在 setBounds() 方法中使用魔术数字。在您的上一个问题中,您已经得到了在不使用魔术数字的情况下解决方案。实际上,您甚至不应该使用 setBounds() 方法。设置组件的大小/位置是布局管理器的工作。
-
不要为动画使用线程。应该使用
Swing Timer
来执行动画。所有对 Swing 组件的更新都应在事件分派线程 (EDT) 上进行。Swing Timer 将在 EDT 上执行。 -
不要创建多个
Icon
实例。一个 Icon 可以被多个组件共享。因此,在循环代码之外,您创建一个 Icon 的单个实例,并将该实例用于所有组件。 -
对于
LineBorder
也是一样的。您只需要一个实例。 -
在您上一个问题的评论中,有人建议您如何使用单个语句编写
randomBarrier()
方法。您在这里发布的代码是完全不必要的。前4个语句中的变量甚至都没有被使用。
但是 JLabels 不显示。
如我之前建议的,您可以在面板上使用 GridLayout
,将标签添加到面板,然后将面板添加到框架。阅读 Swing 教程中有关布局管理器的更多信息和实际示例。
我尝试清除我的绘制方法
没有理由使用自定义的绘制方法。您现在正在使用 Swing 组件 (JLabel),Swing 会为您完成所有绘制工作。另外,如您上一个问题中所提到的,如果您确实需要进行自定义绘制,可以覆盖 paintComponent()
方法。我们不应该不断重复同样的建议。
标签的背景不会改变。
JLabel
是唯一默认不透明的 Swing 组件。因此,在创建每个 JLabel 时需要使用:
label.setOpaque(true);
英文:
-
When posting code don't use the "Code Snippet". Instead you paste your code, select the code and then use the
{}
button to highlight the code. -
Post a proper minimal reproducible example when posting code. This is minimal code that directly demonstrates the stated problem. The code should be in a single file and we should be able to copy/paste/compile and test the code. The point of this is to force you to eliminate all unnecessary code so it is easy to understand the problem. Most time you will find your own problem. You have been asked for an MRE is previous questions. Every question should have an MRE so we don't have to guess what you are doing.
-
It looks to me like you have a 2D grid. Don't use the GroupLayout. This tells me you are using the IDE to generate your code. You are spending time learning the IDE and not learning Swing. You can easily use a
GridLayout
for a 2D grid. -
Don't use static variables. Your width, height, boardWidth and boardHeight variables are not needed. Each Swing component should be responsible for determining its own preferred size. Then after all components are added to the frame, you pack() the frame before making it visible. The frame will then determines its appropriate size. In this case you can use setPreferredSize(...) for each of the JLabels to make them the size of your tile. So outside the loop you create an single instance of a
Dimension
object to be shared by all labels. -
Don't use magic numbers in the setBounds() method. In you last question you were given the solution without using magic numbers. In fact you should not even be using the setBounds() method. It is the job of the layout manager to set the size/location of the component.
-
Don't use a Thread for animation. Animation should be done using a
Swing Timer
. All updates to Swing components should be done on the Event Dispatch Thread (EDT). The Swing Timer will execute on the EDT. -
Don't create multiple instance of your
Icon
. An Icon can be shared by multiple components. So you create a single instance of the Icon outside the looping code and use that instance for all components. -
Same with the
LineBorder
. You only need a single instance. -
In the comments from your last question you were given a suggestion on how to write your
randomBarrier()
method using a single statement. The code you post here is completely unnecessary. The variable from the first 4 statement are not even used.
> but the Jlabels do not show.
As I suggested earlier you can use a GridLayout
on your panel and add the labels to the panel and the panel to the frame. Read the Swing tutorial on Layout Manager for more information and working examples.
> I tried cleaning my paint method
There is no reason to use a custom paint method. You are using Swing components (JLabel) now and Swing will do all the painting for you. Also, as mentioned in your last question, it you ever do need to do custom painting you override the paintComponent()
method. We should not have to keep repeating the same advice.
> the background of the labels doesn't change.
A JLabel
is the only Swing component that is not opaque by default. So you need to use:
label.setOpaque( true );
when you create each JLabel.
答案2
得分: 1
我认为,你需要重写paintComponent(Graphics g)来绘制你的游戏板。你必须将所有想要绘制的内容保存在一个集合中,并在重写的paintComponent方法中进行绘制。
英文:
I think, you have to override paintComponent(Graphics g) for your board.
You have to save everything you want to draw in a Collection and draw them in paintComponent override.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论