ボタンの ActionListener のメソッドから「メイン スレッド」(実行されるスレッドmain()
) に何らかの処理を実行させactionPerformed()
たいのですが、これを実現する方法がわかりません。
もう少しコンテキスト:
現在、Swing (テトリスのフレーバー) を使用して 2D ゲームをプログラミングしています。
アプリケーションが起動すると、ゲームのメイン メニューを表示するウィンドウが開きます。ユーザーにはいくつかの可能性が提示されます。そのうちの 1 つは、「開始」ボタンを押してゲームを開始することです。これにより、ゲーム パネルが表示され、ゲームのメイン ループがトリガーされます。
2 つのパネル (メイン メニューのパネルとゲームのパネル) を切り替えることができるようにするために、CardLayout マネージャーを使用していますshow()
。
アイデアは、スタート ボタンに次のようなリスナーを持たせたいということです。
public class StartListener implements ActionListener {
StartListener() {}
public void actionPerformed(ActionEvent e) {
displayGamePanel();
startGame();
}
}
actionPerformed()
がイベント ディスパッチ スレッドから呼び出されるため、これは機能しません。そのため、 startGame()
(メイン ループをトリガーする: ゲーム ロジックの更新 +repaint()
各フレームでの呼び出し) への呼び出しは、スレッド全体をブロックします。
私が現在これを処理している方法はactionPerformed()
、ブール値のフラグ値を変更することです。public void actionPerformed(ActionEvent e) {
startPushed = true;
}
これは、最終的にメインスレッドによってチェックされます。
while (true) {
while (!g.startPushed) {
try {
Thread.sleep(100);
} catch (Exception e) {}
}
g.startPushed = false;
g.startGame();
}
しかし、この解決策は非常に洗練されていないと思います。
Concurrency in Swingのレッスンを読みましたが、まだ混乱しています (ワーカースレッドを実装する必要がありますか? それは少しやり過ぎではありませんか?)。実際のマルチスレッド作業はまだ行っていないので、少し迷っています。
メインスレッド(無期限にスリープし、ユーザーのアクションを待っている)に「よし、今起きてこれをする(ゲームパネルを表示してゲームを開始する)」ように伝える方法はありませんか?
ご協力いただきありがとうございます。
編集: 明確にするために、これは私のゲームループがどのように見えるかです:
long lastLoopTime = System.currentTimeMillis();
long dTime;
int delay = 10;
while (running) {
// compute the time that has gone since the last frame
dTime = System.currentTimeMillis() - lastLoopTime;
lastLoopTime = System.currentTimeMillis();
// UPDATE STATE
updateState(dTime);
//...
// UPDATE GRAPHICS
// thread-safe: repaint() will run on the EDT
frame.repaint()
// Pause for a bit
try {
Thread.sleep(delay);
} catch (Exception e) {}
}