3

JFrames は、invokeLater を使用してイベント ディスパッチ スレッド (EDT) で安全に作成する必要があることを理解しています。メイン メソッド内で JFrames を 2 つ作成しようとしています。

コード:

public void run() {     

    // Handle Menu When Open
    menu.setVisible(true);
    while(menu.isVisible())
    {
        if(menu.isShowing() == false) {
            showMenu = false;
            showSimulation = true;
        }
    }
    menu.setVisible(false);

    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            int[] dims = menu.SizeSetting();
            simulation = new Simulation(dims[0], dims[1]);
        }
    });

    simulation.run();
}

これで、メニューが作成されます (ここで必要な処理はごくわずかであるため、これは問題なく機能するようです)。この後、メニューが使用され、ボタンmenu.setVisible(false)が呼び出されます。その後、EDT でメソッドをキューに入れます。Simulation は から派生したクラスJFrameです。そのコンストラクタは次のとおりです。

public Simulation(int width, int height) {
    this.setVisible(false);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setTitle("Traffic Light System - Simulation");
    grid = new Grid(0, 0);
    ready = false;

    grid = new Grid(width, height);
    addComponentsToPane(); // Set up visualization of grid here

    // Introduce cars here? e.g. grid.Get(0, 0).addCars(new Car[])?

    ready = true;
    setVisible(true);
}

addComponentsToPane()メソッドがすべての必要なコンテンツを JFrame に追加する場所。このコンストラクターの後に呼び出される run() メソッドは単純です。

public void Run() { 
    while(isVisible()) {
        OneStep();
    }
    setVisible(false);
}

ただし、このコードを実行すると、メニュー ウィンドウしか表示されません。メニューを終了し、シミュレーション ウィンドウが表示されたときに、プログラムが終了したように見えます。

ここで私が間違っていることはありますか?

4

1 に答える 1

6

あなたが何をしようとしているのか完全には理解できませんが、間違いなく間違っていると言えます。イベントwhile (true)駆動型システムではなく、ループが存在してはならず、イベント駆動型プログラミングの概念に反しています。代わりに、コードはこの終わりのない while ループではなく、イベントへの反応によって状態を変更する必要があります。

また、記述されたコードは、作成される前にシミュレーションでメソッドを呼び出すリスクがあることに注意してください。Run メソッド (run という名前にする必要があります) が呼び出される場所とは別のスレッドで作成されることに注意してください。実行の順序を保証することはできず、Runnable の呼び出しに遅延が生じるため、実際には間違った順序で発生する可能性があります。これは、呼び出される前にまずイベント スレッドのキューに入れられる必要があるためです。

より良い助けを得るために、あなたの問題を示す最小限のコンパイル可能で実行可能なプログラムを作成して投稿することを検討してください。


編集 1
また、大文字で始まるクラス名、小文字で始まるメソッドおよび変数名の指定など、Java の命名規則を学習して使用する必要があります。


編集2 あなたは次のように述べています:

基本的に、このインスタンス化が完了すると、プログラムは対話なしで自分自身を更新するだけです。それがループのアイデアでした。ループはシミュレーションを更新し、次に表示されているものを更新します。

Swing シミュレーションを実行しようとしている場合は、単純にアニメーション ループにSwing Timerを使用してみませんか? あなたのコードは、ほぼ確実に Swing スレッド化の失敗を引き起こします。


編集 3 3
回目または 4 回目の読み取りでは、メイン アプリケーションからモーダルな方法でメニュー ビューを表示しようとしているように見えます。その場合は、1) メニュー ウィンドウにモーダル JDialog を使用することを検討してください。この方法でウィンドウを起動できます。メニュー ウィンドウが表示されなくなるまで、起動コードはこの場所で停止します。その後、アニメーション ウィンドウを表示できます。または 2) CardLayout を使用してビューを交換します。ここには、メニュー JPanel を最初に表示する単一の JFrame アプリケーションがあります。次に、メニューが処理されたら、CardLayout スワップ ビューを使用して、アニメーションがその場所に表示されるようにします。

于 2014-02-27T20:55:07.977 に答える