2

私は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ステートメントは、各セルがそれぞれの状態で登録されていることを示しています。

4

3 に答える 3

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)を呼び出す必要がないもう1つのことは、デフォルトであるためです。また、JLabelの背景を変更するには、追加する必要があります(デフォルトでは透過的であるため)。

lab.setOpaque(true);
于 2013-02-09T07:32:19.713 に答える
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

コード内のコメントを参照してください。

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 に答える