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 方法使用新按钮更新 controlPnl GUI。dmc.moveTo 方法中最多有两个 Thread.sleep 调用,我认为它们是在 controlPnl GUI 更新之前被调用的。我已经注释掉了 dmc.moveTo 之后的两个方法调用,这会将 GUI 更改回调用之前的状态,并且 controlPnl 直到 moveTo 完成执行才完成更新。我需要的是 GUI 在 moveTo 方法开始执行之前完成更新并使线程进入睡眠状态。有什么方法可以在 Java 6 中实现这一点吗?

如果重要,moveTo 方法会将 LEGO Mindstorm 机器人移动到用户定义的路径上的指定点。正在更新的 GUI 提供 Swing 组件(JButtons 和 JRadioButtons)供用户在机器人导航时控制机器人。addRemote 方法更改了一组 Swing 组件供用户使用,moveTo 方法向机器人发送命令以实际执行运动(通过告诉它的电机移动,休眠正确的时间量,然后告诉它的电机停止移动)。我正在使用状态机模式,此方法是处理来自 UI 的事件的控制器的一部分。

4

2 回答 2

0

You have a single GUI thread. Don't use it to call other things; if you do, those things have to complete before anything else is going to happen in your GUI.

At the very least you would want to start a new thread to perform your dmc.moveTo(destination). More than likely this isn't the only place you're doing this, and probably want an Executor set up to perform these tasks.

Without knowing more about your code (especially since you're using a static method) I can't comment on how you would want to set up the Executor but the simplest example of using a Thread would be:

 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();
}

This creates a new Thread that executes your (anonymous) Runnable which performs your moveTo(). Note this is far less efficient than having an Executor that is ready to run your task; it has to create a new Thread every time. However, if that's not an issue in terms of the performance you need then it's perfectly fine. Also note that because I'm referencing destination directly inside the anonymous inner class, it has to be declared final when passed into your method.

于 2013-02-12T16:58:34.163 回答
0

由于您moveTo需要很长时间,您不应该在主事件处理线程上执行它。相反,moveTo更新 GUI 并在单独的线程中开始实际移动。移动完成后,使用SwingUtilities.invokeLater进行第二组 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 响应,但第二个changeState会延迟到dmc.moveTo完成。

(将这些东西分解成单独的方法可能比使用 Runnable-in-a-Runnable 匿名类更有意义)

于 2013-02-12T18:06:00.507 回答