1

私は自分のJavaクラスでアプリケーションを開発していて、奇妙な問題で壁にぶつかりました。データをグリッドで表す必要があるため、GridLayoutを使用するのは当然の選択ですが、ここに問題があります。私はほとんど空のフレームを取得し続けます(左上隅にある小さな白い長方形に注意してください)。

問題

この結果を生成するコードスニペットは次のとおりです

//not important class code 
public static void main(String args[]) {    
    JFrame frame = new JFrame("Wolves & Rabbits");
    frame.setSize(640, 480);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //want to create a 12x9 grid with 2 black and 4 pink rectangles
    Board board = new Board(12, 9, 2, 4, 1000);

    frame.add(board);

    frame.setResizable(false);
    frame.setVisible(true);
}

//Board.java (Board class) extends JPanel
public JPanel fields[][];
private Integer boardWidth, boardHeight;
private ArrayList<AnimalThread> animals;
private Integer wolvesCount, rabbitsCount;

public Board(int w, int h) {
    super(new GridLayout(h, w, 4, 4));

    fields = new JPanel[w][h];
    boardWidth = new Integer(w);
    boardHeight = new Integer(h);
    animals = null;
    wolvesCount = new Integer(0);
    rabbitsCount = new Integer(0);

    //creating white rectangles
    for (int i = 0; i < boardHeight; i++)
        for (int j = 0; j < boardWidth; j++) {
            fields[j][i] = new JPanel(true);
            fields[j][i].setBackground(AnimalThread.NONE);
            this.add(fields[j][i]);
        }

    AnimalThread.setLinkToBoard(this);
}

public Board(int w, int h, int wolves, int rabbits, int k) {
    this(w, h);

    animals = new ArrayList<AnimalThread>();

    while (boardWidth*boardHeight < 2*wolves*rabbits) {
        wolves--;
        rabbits--;
    }       
    wolvesCount = wolves;
    rabbitsCount = rabbits;

    WolfThread.setRabbitsCount(rabbitsCount);

    //randomly place colored rectangles
    this.randomize(wolves, rabbits, k);     
}

奇妙なことに、Boardクラスをまったく変更せず、mainメソッドを少し変更するだけで、適切なグリッドを表示できました。

問題は解決された

この場合の主な方法は

//not important class code
public static void main(String args[]) {    
    JFrame frame = new JFrame("Wolves & Rabbits");
    frame.setSize(640, 480);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Board board = new Board(12, 9, 2, 4, 1000);

    //THE CHANGE!
    JPanel panel = new JPanel(new GridLayout(12, 9, 4, 4));
    for (int i = 0; i < 9; i++)
        for (int j = 0; j < 12; j++) {
            JPanel tmp = board.fields[j][i];
            panel.add(tmp);
        }
    frame.add(panel);

    frame.setResizable(false);
    frame.setVisible(true);
}

誰もがこの苛立たしい問題の原因を知っていますか?手がかりをいただければ幸いです。

4

1 に答える 1

1

Swingを使用している場合は、EDTでSwingUIコードを実行する必要があります。したがって、少なくともメインメソッドは次のようになります。

public static void main(String args[]) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            JFrame frame = new JFrame("Wolves & Rabbits");
            frame.setSize(640, 480);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            // want to create a 12x9 grid with 2 black and 4 pink rectangles
            Board board = new Board(12, 9, 2, 4, 1000);

            frame.add(board);

            frame.setResizable(false);
            frame.setVisible(true);
        }
    });
}

他のスレッドからSwingオブジェクトである変数にアクセスすると、EDTで問題が発生します。これらの問題の多くは断続的で追跡が困難です(ほとんどの並行性の問題と同様)。

'AnimalThread'オブジェクトの名前は、そのスレッドを暗示しているようです。EDT上で「生きている」オブジェクトを直接スイングすることはできません(実際には、あなたが示したように:-)。別のスレッドがEDTで何かを変更したい場合は、「SwingUtilities.invokeLater」または「SwingUtilities.invokeAndWait」メソッドを使用する必要があります。

于 2012-12-09T20:19:14.623 に答える