1
public static void moveTo(Coordinate destination) {

    changeState(State.NAVIGATION);
    controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION));

    dmc.moveTo(destination);

    changeState(State.IMMEDIATE);
    controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE));
}

このコードでは、addRemoteメソッドがcontrolPnlGUIを新しいボタンで更新します。dmc.moveToメソッドには最大2つのThread.sleep呼び出しがあり、controlPnlGUIが更新される前に呼び出されていると思います。dmc.moveToの後に2つのメソッド呼び出しをコメントアウトしました。これにより、GUIが呼び出し前の状態に戻り、moveToの実行が完了するまでcontrolPnlの更新が完了しません。必要なのは、moveToメソッドの実行が開始され、スレッドがスリープ状態になる前に、GUIが更新を完了することです。Java 6でこれを実現する方法はありますか?

重要な場合、moveToメソッドは、レゴマインドストームロボットをユーザーが定義したパス上の指定されたポイントに移動します。更新中のGUIは、ユーザーが移動中にロボットを制御するためのSwingコンポーネント(JButtonsおよびJRadioButtons)を提供します。addRemoteメソッドは、ユーザーが使用するSwingコンポーネントのセットを変更し、moveToメソッドは、実際に移動を実行するコマンドをロボットに送信します(モーターに移動するように指示し、正しい時間スリープしてから、モーターに次のように指示します。移動を停止します)。ステートマシンパターンを使用しています。このメソッドは、UIからのイベントを処理するコントローラーの一部です。

4

2 に答える 2

0

単一のGUIスレッドがあります。他のものを呼び出すためにそれを使用しないでください。そうした場合、GUIで他のことが起こる前に、これらのことを完了する必要があります。

少なくとも、を実行するために新しいスレッドを開始する必要がありますdmc.moveTo(destination)。おそらく、これを実行しているのはこれだけではなく、おそらくこれらのタスクを実行するようにエグゼキュータを設定する必要があります。

コードについて詳しく知らなければ(特に静的メソッドを使用しているため)、どのように設定するかについてコメントすることはできませんExecutorが、を使用する最も簡単な例は次のThreadとおりです。

 public static void moveTo(final Coordinate destination) {

    changeState(State.NAVIGATION);
    controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION));

    new Thread(new Runnable() {
                   public void run() {
                       dmc.moveTo(destination);
                       changeState(State.IMMEDIATE);
                       controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE));
                   }
               }).start();
}

これにより、Threadを実行する(匿名の)Runnableを実行する新しいが作成されますmoveTo()。これはExecutor、タスクを実行する準備ができているを持っているよりもはるかに効率が悪いことに注意してください。Thread毎回新しいものを作成する必要があります。ただし、それが必要なパフォーマンスの観点から問題ではない場合は、まったく問題ありません。またdestination、匿名内部クラス内で直接参照しているためfinal、メソッドに渡すときに宣言する必要があることにも注意してください。

于 2013-02-12T16:58:34.163 に答える
0

moveTo時間がかかるので、メインイベント処理スレッドで実行しないでください。代わりにmoveTo、GUIを更新して、別のスレッドで実際の移動を開始してください。移動が完了したら、を使用SwingUtilities.invokeLaterして2番目のGUI更新セットを実行します。

private static ExecutorService executor = Executors.newCachedThreadPool();

public static void moveTo(final Coordinate destination) {

    changeState(State.NAVIGATION);
    controlPnl.addRemote(Remote.createRemote(remoteType.NAVIGATION));

    executor.execute(new Runnable() {
      public void run() {
        dmc.moveTo(destination);
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            changeState(State.IMMEDIATE);
            controlPnl.addRemote(Remote.createRemote(remoteType.IMMEDIATE));
          }
        });
      }
    });
}

このようmoveToにして、GUI更新の初期セットが実行され、すぐに戻り、イベントループが解放されて、GUIの応答性が維持されますが、2番目のセットは完了changeStateするまで遅延されます。dmc.moveTo

(Runnable-in-a-Runnable匿名クラスを使用するよりも、このようなものを別々のメソッドに分解する方が理にかなっている場合があります)

于 2013-02-12T18:06:00.507 に答える