2

我对使用 swing 进行 GUI 编程还很陌生,并且我确信这是一个菜鸟问题。

我创建了一个 JFrame,里面有一个 JPanel。然后我尝试为数组中的每个元素添加一个 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 语句显示每个单元格都在注册其各自的状态。

4

3 回答 3

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);
}
于 2013-02-09T08:09:00.930 回答
3

据我所知,当您将组件添加到任何可见容器时,您应该调用 revalidate/repaint,这样您就可以将 setVisible 和添加面板移动到最后一个语句的框架:

// 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);
于 2013-02-09T07:32:19.713 回答
3

查看代码中的注释:

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
    }
}

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

于 2013-02-09T16:22:34.717 回答