0

私はJavaとスレッド全般に不慣れで、Javaで次のGUIアプリケーションを持っています:

  1. フレーム内で、ユーザーが任意の場所でマウスをクリックすると、画像が表示されます。

  2. 画像が表示されると、リアルタイム タイマーの実行が開始され、jLabel ユーザーが GUI で選択した値に応じて、タイマーが最大 5 秒まで更新されます。

  3. 同時にサウンドクリップが再生されます。画像と音が一致すると、ユーザーはクリックしてタイマーを停止します。一致または不一致を反映するために、いくつかの jLabel 値が更新されます。そうでない場合、ユーザーはアイドル状態になり、タイマーが切れた後にイメージ/サウンド クリップのペアが変更されるのを待ちます。ユーザーがタイマーを停止するかタイマーが切れると、アプリケーションは事前に選択された画像間の時間間隔の値を待機し、次の画像/サウンド値に進みます。

私は次の構造を持っています:

電話する

while(true)
{
SwingUtilities.invokeAndWait(displayTimer);
}

私のrun()方法で。

私のRunnable

private final Runnable displayTimer= new Runnable()
{
public void run()
{
 displayElapsed(System.currentTimeMillis() - startTime);
}

};

後でstartTime初期化され、タスクの開始の開始基準点になります。

私のdisplayElapsed()方法は面倒で、タイマーがユーザー入力または非アクティブによって停止したかどうかを確認します。そうでない場合は、jLabelタイマーの責任者を更新します。存在する場合は、startInteraction()メソッドを呼び出します。

startInteraction()新しい画像と音声を用意し、それぞれを表示・再生し、新しいスレッドupdaterを作成して起動します。

mouseListenerユーザー入力をリッスンするもあります。ユーザーがクリックすると呼び出さupdater.interrupt()れます。

では、質問です。私は、スイングがスレッドセーフでないことを知っています。ユーザーのマウスクリックにすぐに応答しないこともあれば、適切な待ち時間なしで 2 つの画像/音声のペアを通過することもあるため、動作には間違いなく問題があります。ラベルもすぐには更新されません。

一般的に、構造はごちゃごちゃしているように見えますが、論理的に説明することはできません。

私が知っているのは、displayElapsed私が行うたびに新しいスレッドを開始し、ユーザーまたはアイドルストップがあるたびに中断することだけです。したがって、技術的には、各スレッドは順番に並んでいる必要があります。

これを行うにはもっと良い方法が必要であり、これを書き直す上で何が良いスタートになるかを知りたかったのです。

4

1 に答える 1

2

SwingWorkerに関するこの記事をご覧ください。プログラムが実行している問題は、ランナブルが EDT で同期的に実行されているため、イベント ディスパッチ スレッド (ユーザー インターフェイスをレンダリングするために使用される唯一のスレッド) が無限ループによってブロックされていることです。

必要なのは、別のスレッドでタイマー コードを実行し、このスレッドで定期的なタスクを投稿して、EDT のラベルを更新することです。SwingWorker クラスは、これを実現するのに役立ちます。これを行うには、

  1. サブクラス化 (または匿名作成) SwingWorker
  2. doInBackgroundタイミングループを実装する
  3. タイミングループ内でpublish、タイムスタンプ(またはラベルに入れたいもの)を渡すために呼び出します
  4. processラベルを更新する実装
  5. ワーカーをインスタンス化して呼び出しますrun
于 2012-09-28T08:10:24.243 に答える