JPanel上的元素没有出现

时间:2013-02-09 06:47:44

标签: java swing

我对使用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语句显示每个单元格都以其各自的状态进行注册。

3 个答案:

答案 0 :(得分:3)

我能够得到一些工作(至于它是否是另一回事)

enter image description here

基本上我所做的一切(除了将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
    }
}

注意:通常,您甚至不需要设置组件的首选大小,因为每个组件都有一个首选大小。但在这种情况下,您没有在标签上添加文字或图标,因此它没有首选尺寸。