我对使用swing进行GUI编程相当新,并且我已经确定了noob问题。
我在其中创建了一个带有JPanel的JFrame。然后我试图为数组中的每个元素添加一个JLabel。问题是元素没有出现在面板上。我已经检查过以确保数组元素使用println语句进行注册,所以这不是问题所在。我猜我在某个地方错过了一个声明......请指教。
这是我的代码:
public class MazeFrame extends javax.swing.JFrame {
Maze m;
/**
* Creates new form MazeFrame
*/
public MazeFrame(Maze m) {
this.m = m;
setSize(new Dimension(800, 600));
JPanel pan = new JPanel();
add(pan);
setVisible(true);
// pan.setBackground(Color.yellow);
pan.setLayout(new GridLayout(m.width, m.height));
for (int curr = 0; curr < m.height; curr++){
for (Cell c: m.maze[curr]){
JLabel lab = new JLabel();
switch (c.state){
case border:
lab.setBackground(Color.black);
System.out.println("addedborder");
break;
case wall:
lab.setBackground(Color.DARK_GRAY);
System.out.println("addedwall");
break;
case open:
lab.setBackground(Color.LIGHT_GRAY);
System.out.println("addedopen");
break;
case travelled:
lab.setBackground(Color.RED);
}
lab.setSize(new Dimension(50, 50));
lab.setVisible(true);
pan.add(lab);
// System.out.println("added");
}
}
pan.revalidate();
pan.repaint();
}
}
这是迷宫类:
package robots;
import java.util.Random;
public class Maze {
public Cell[][] maze;
final int width;
final int height;
public Maze(){
width = 20;
height = 20;
maze = new Cell[width][height];
for (int row = 0; row < height; row++){
for (int col = 0; col < width; col++){
maze[row][col] = new Cell(row, col);
}
}
// set borders
for (int curr = 0; curr < height; curr++) {
maze[0][curr].setState("border");
maze[curr][0].setState("border");
maze[height - 1][curr].setState("border");
maze[curr][width - 1].setState("border");
}
// initially mark all cells as walls
for (int row = 1; row < height - 1; row++) {
for (int col = 1; col < width - 1; col++) {
maze[row][col].setState("wall");
}
}
}
private boolean isValidTurn(int row, int col) {
if (row >= 0 && col < width && col > 0 &&
row < 20 && (!this.maze[row][col].getState().matches("open"))) {
return true;
}
return false;
}
public void makeRoute() {
Random r = new Random();
int row = 0;
int col = r.nextInt(width);
maze[row][col].setState("open");
row = row+1;
maze[row][col].setState("open");
// System.out.println(this);
while (row < (this.height - 1)) {
// Assuming the mouse moves in only 3 directions left right or down
// in the maze. 0 indicates left turn 1 indicates right turn and
// 2 indicates down movement in the maze.
int nextDir = r.nextInt(3);
switch (nextDir) {
case 0: // left turn
if (this.isValidTurn(row, (col - 1))) {
--col;
this.maze[row][col].setState("open");
}
break;
case 1: // right turn
if (this.isValidTurn(row, (col + 1))) {
++col;
this.maze[row][col].setState("open");
}
break;
case 2: // down movement
++row;
this.maze[row][col].setState("open");
break;
}
System.out.println("turn : " + nextDir);
// System.out.println(this);
}
System.out.println(this);
}
}
class Cell {
int row;
int col;
int above, below, toLeft, toRight;
enum state {border, wall, open, travelled};
state state;
public Cell(int row, int col){
this.row = row;
this.col = col;
above = row + 1;
below = row -1;
toLeft = col -1;
toRight = col +1;
}
@Override
public String toString(){
String out = new String();
if (state == state.border) {
out = "0";
}
if (state == state.wall) {
out = "#";
}
if (state == state.open) {
out = ".";
}
if (state == state.open) {
out = "-";
}
return out;
}
public void setState(String toSet){
switch (toSet){
case "border":
state = state.border;
break;
case "wall":
state = state.wall;
break;
case "open":
state = state.open;
break;
case "travelled":
state = state.travelled;
break;
}
}
public String getState() {
return state.toString();
}
}
但是,正如我所说,我知道迷宫类工作正常,因为它在运行时完美地输出到控制台。此外,MazeFrame类中的println语句显示每个单元格都以其各自的状态进行注册。
答案 0 :(得分:3)
我能够得到一些工作(至于它是否是另一回事)
基本上我所做的一切(除了将setVisible
移动到构造函数的末尾之外)都使lab
不透明......
public TestMaze(Maze m) {
this.m = m;
setSize(new Dimension(800, 600));
JPanel pan = new JPanel();
add(pan);
pan.setLayout(new GridLayout(m.width, m.height));
for (int curr = 0; curr < m.height; curr++) {
for (Cell c : m.maze[curr]) {
JLabel lab = new JLabel();
lab.setOpaque(true); // <-- Add me...
switch (c.state) {
case border:
lab.setBackground(Color.black);
break;
case wall:
lab.setBackground(Color.DARK_GRAY);
break;
case open:
lab.setBackground(Color.LIGHT_GRAY);
break;
case travelled:
lab.setBackground(Color.RED);
}
lab.setSize(new Dimension(50, 50));
lab.setVisible(true);
pan.add(lab);
// System.out.println("added");
}
}
setVisible(true);
}
答案 1 :(得分:2)
我知道你应该在向任何可见容器添加组件时调用revalidate / repaint,这样你就可以移动你的setVisible&amp;将面板添加到帧到最后一个语句:
// update panel
pan.revalidate();
pan.repaint();
// adding panel to frame
this.add(pan);
this.pack();
this.setVisible(true);
另一件事你不需要调用JLabel.setVisible(true),因为它是默认的,也是为了改变你需要添加的JLabel的背景(因为它默认是透明的):
lab.setOpaque(true);
答案 2 :(得分:2)
请参阅代码中的注释:
public class MazeFrame extends javax.swing.JFrame {
Maze m;
/**
* Creates new form MazeFrame
*/
public MazeFrame(Maze m) {
this.m = m;
// Don't manually set the size of a frame. Let the preferred size of you components determine the size.
// This is done by invoking pack() after all components have been added to the frame.
// setSize(new Dimension(800, 600));
JPanel pan = new JPanel();
add(pan);
// setVisible(true); // do after all components added.
// pan.setBackground(Color.yellow);
pan.setLayout(new GridLayout(m.width, m.height));
for (int curr = 0; curr < m.height; curr++){
for (Cell c: m.maze[curr]){
JLabel lab = new JLabel();
lab.setOpaque(true); // as suggested by MadProgrammer
switch (c.state){
case border:
lab.setBackground(Color.black);
System.out.println("addedborder");
break;
case wall:
lab.setBackground(Color.DARK_GRAY);
System.out.println("addedwall");
break;
case open:
lab.setBackground(Color.LIGHT_GRAY);
System.out.println("addedopen");
break;
case travelled:
lab.setBackground(Color.RED);
}
// Set the preferred size so layout managers can do there job
// lab.setSize(new Dimension(50, 50));
lab.setPreferredSize(new Dimension(50, 50));
// Not required. This is the default for all components except top level containers like JFrame, JDialog
// lab.setVisible(true);
pan.add(lab);
// System.out.println("added");
}
}
// No neeed to revalidate or repaint because the frame is not visible yet
// pan.revalidate();
// pan.repaint();
pack(); // let the layout manager determine the size of the frame
setVisible(); // show the frame
}
}
注意:通常,您甚至不需要设置组件的首选大小,因为每个组件都有一个首选大小。但在这种情况下,您没有在标签上添加文字或图标,因此它没有首选尺寸。