2017-06-11 4 views
3

意図したとおりに動作しないActionListenersに問題があります。ここでは、それらのコードは次のとおりです。 Java ActionListenerがJMenuItemで動作しない

import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 

public class GameOfLife extends JFrame implements ActionListener 
{ 
    Timer timer = new Timer(700, this); 
    Table world; 
    JMenuBar menuBar; 
    JMenu gameMode; 
    JMenu actions; 
    JMenuItem custom, demo, random, start, pause, save, load; 

    public GameOfLife(int width, int height) 
    { 
     super(); 
     world = new Table(width, height); 
     CreateMenu(); 

     this.setContentPane(world); 
     this.setJMenuBar(menuBar); 
     this.setPreferredSize(new Dimension(1200, 900)); 
     this.setVisible(true); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.pack(); 
     StartRandom(); 
    } 

    private void CreateMenu() 
    { 
     menuBar = new JMenuBar(); 
     gameMode = new JMenu("Game Mode"); 
     actions = new JMenu("Actions"); 

     custom = new JMenuItem("Custom Game"); 
     custom.addActionListener(new ActionListener(){ 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       StartCustom(); 
      } 
     }); 
     gameMode.add(custom); 

     demo = new JMenuItem("Demo Game"); 
     demo.addActionListener(new ActionListener(){ 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       StartDemo(); 
      } 
     }); 
     gameMode.add(demo); 

     random = new JMenuItem("Random Game"); 
     random.addActionListener(new ActionListener(){ 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       StartRandom(); 
      } 
     }); 
     gameMode.add(random); 
     menuBar.add(gameMode); 
    } 

    private void Demo() 
    { 
     int[] x = 
     { 
      5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 
      12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 17, 17, 17, 17, 17, 17 
     }; 
     int[] y = 
     { 
      7, 8, 9, 13, 14, 15, 5, 10, 12, 17, 5, 10, 12, 17, 5, 10, 12, 17, 7, 8, 9, 13, 14, 15, 7, 8, 9, 
      13, 14, 15, 5, 10, 12, 17, 5, 10, 12, 17, 5, 10, 12, 17, 7, 8, 9, 13, 14, 15 
     }; 
     int i = 0; 
     while (i < x.length) 
     { 
      world.SetStartPosition(x[i], y[i++]); 
     } 
    } 

    private void StartCustom() 
    { 
     // TO-DO 
    } 

    private void StartDemo() 
    { 
     Demo(); 
     Game(); 
    } 

    private void StartRandom() 
    { 
     world.RandomTable(); 
     Game(); 
    } 

    private void Game() 
    { 
     while (world.CountAliveCells() > 0) 
     { 
      timer.start(); 
     } 
    } 

    public static void main(String[] args) { 
     new GameOfLife(20,20); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     world.UpdateCellNeighbors(); 
     world.UpdateTable(); 
    } 

} 

私はゲームモードメニュー、アプリケーションがフリーズからのメニュー項目のいずれかを押すと、私は他に何もなく、ただEclipseの停止ボタンからそれを止めることはできない

。私も addMouseListenerで試してみましたが、コンソールでの書き込みのみで動作します。 StartDemoStartRandomメソッドは、クラスコンストラクタで呼び出された場合に機能しますが、アクションリスナメソッドで呼び出された場合にはアプリケーションをフリーズします。また、文字通り何もしない StartCustomメソッドでもアプリケーションがフリーズします。

編集: 私はSwing TimerでThread.sleep関数を変更しましたが、問題はまだ同じです。メニューボタンからゲームモードを選択しようとすると、アプリケーションがフリーズしますが、クラスコンストラクターからStartDemoまたはStartRandomメソッドが呼び出されたときは、完全に機能します。

+1

作り、EDTのコンテキスト内で登録ActionListener S actionPerformed方法をトリガー:あなたは 'StartCustom'と'呼び出すcustom' 'にActionListener's'に追加しましたStartDemo'、おそらくあなたが意図したものではない – MadProgrammer

+0

メソッド名は大文字で始めるべきではありません。 Java APIからメソッドを見せてください。 Javaの規約に従ってください。 – camickr

答えて

1

FYI:あなたはあなたの実際の問題に関しては

を意図したもので、おそらく、StartCustomStartDemoをしませ呼び出すcustomActionListener秒に追加されました...

アプリケーションがフリーズし私がすることができます何もしないでEclipse停止ボタンから停止してください。

スイングでは、これはイベントディスパッチスレッドをいくつかブロックしたことを意味します我々はGameを確認できる方法

私たちはあなたのコードを詳しく見てみたら...

private void Game() 
{ 
    while (world.CountAliveCells() > 0) 
    { 
     world.UpdateCellNeighbors(); 
     world.UpdateTable(); 
     try { 
      Thread.sleep(700); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

は、ループを実行しています。 GameActionListeneractionPerformedメソッドのコンテキスト内から呼び出されるため、Event Dispatching Threadのコンテキスト内で呼び出されることが保証されています。つまり、EDTは実行されなくなり、新しいイベントを処理できなくなりますイベントキューに格納されます。

詳細はConcurrency in Swingを参照してください。

これを変更するにはいくつかの方法がありますが、最も簡単なのはSwing Timerです(詳細はHow to use Swing Timersを参照)。

この問題を解決するソリューションを選択するときは、スイングはスレッドセーフではないことを覚えておいてください。つまり、EDTのコンテキスト内でUIの更新を行わなければなりません。スイングTimerは、シンプルながら、その安全なオプションFYI

関連する問題