您可以在后台使用 运行 中调用的方法发布吗?

Can you use publish from a method called in run in background?

我在后台使用 swingworker 运行 方法并定期更新 gui 信息,但据我发现无法从另一个 class 调用发布。这是我的 Swingworker 的名称:

private void start() {
    worker = new SwingWorker <Void, String>() {

        @Override
        protected Void doInBackground() throws Exception {
            navigator.navigator();

            return null;
        }
        @Override
        protected void process(List<String> chunks) {
            for (String line : chunks) {
                txtrHello.append(line);
                txtrHello.append("\n");
            }
        }
        @Override
        protected void done() {

        }

    };
    worker.execute();
}

现在我想从导航器方法调用 publish(String);,我该怎么做?将我所有的方法都移到 doInBackground() 中是不可能的。

可能的解决方案是向您的 Navigator 对象添加一个观察者,关键是以某种方式允许 Navigator 与其状态已更改的任何侦听器(此处为 SwingWorker)进行通信:

  • 为 Navigator 提供一个 PropertyChangeSupport 对象以及一个 addPropertyChangeListener(PropertyChangeListener listener) 方法,用于将传入的侦听器添加到支持对象。
  • 为 Navigator 提供某种类型的 "bound" 属性,一个字段,当其状态发生变化时,通常在 setXxxx(...) 类型的方法中,通知支持对象这一变化。
  • 然后在您的 SwingWorker 构造函数中,将 PropertyChangeListener 添加到您的 Navigator 对象。
  • 在此侦听器中,使用 Navigator 对象中的新数据调用 publish 方法。

例如:

import java.awt.event.ActionEvent;
import java.beans.*;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class PropChangeSupportEg extends JPanel {
   private MyNavigator myNavigator = new MyNavigator();
   private JTextField textField = new JTextField(10);

   public PropChangeSupportEg() {
      textField.setFocusable(false);
      add(textField);
      add(new JButton(new StartAction("Start")));
      add(new JButton(new StopAction("Stop")));
   }

   private class StartAction extends AbstractAction {
      public StartAction(String name) {
         super(name);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         if (myNavigator.isUpdatingText()) {
            return; // it's already running
         }
         MyWorker worker = new MyWorker();
         worker.execute();
      }
   }

   private class StopAction extends AbstractAction {
      public StopAction(String name) {
         super(name);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         myNavigator.stop();
      }
   }

   private class MyWorker extends SwingWorker<Void, String> {
      @Override
      protected Void doInBackground() throws Exception {
         if (myNavigator.isUpdatingText()) {
            return null;
         }

         myNavigator.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
               if (MyNavigator.BOUND_PROPERTY_TEXT.equals(evt.getPropertyName())) {
                  publish(evt.getNewValue().toString());
               }
            }
         });
         myNavigator.start();
         return null;
      }

      @Override
      protected void process(List<String> chunks) {
         for (String chunk : chunks) {
            textField.setText(chunk);
         }
      }


   }

   private static void createAndShowGui() {
      PropChangeSupportEg mainPanel = new PropChangeSupportEg();

      JFrame frame = new JFrame("Prop Change Eg");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class MyNavigator {
   public static final String BOUND_PROPERTY_TEXT = "bound property text";
   public static final String UPDATING_TEXT = "updating text";
   private static final long SLEEP_TIME = 1000;
   private PropertyChangeSupport pcSupport = new PropertyChangeSupport(this);
   private String boundPropertyText = "";
   private String[] textArray = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
   private int textArrayIndex = 0;
   private volatile boolean updatingText = false;

   public void start() {
      if (updatingText) {
         return;
      }
      updatingText = true;
      while (updatingText) {
         textArrayIndex++;
         textArrayIndex %= textArray.length;
         setBoundPropertyText(textArray[textArrayIndex]);
         try {
            Thread.sleep(SLEEP_TIME);
         } catch (InterruptedException e) {}
      }
   }

   public void stop() {
      setUpdatingText(false);
   }

   public String getBoundPropertyText() {
      return boundPropertyText;
   }

   public boolean isUpdatingText() {
      return updatingText;
   }

   public void setUpdatingText(boolean updatingText) {
      boolean oldValue = this.updatingText;
      boolean newValue = updatingText;
      this.updatingText = updatingText;
      pcSupport.firePropertyChange(UPDATING_TEXT, oldValue, newValue);
   }

   public void setBoundPropertyText(String boundPropertyText) {
      String oldValue = this.boundPropertyText;
      String newValue = boundPropertyText;
      this.boundPropertyText = boundPropertyText;
      pcSupport.firePropertyChange(BOUND_PROPERTY_TEXT, oldValue, newValue);
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.removePropertyChangeListener(listener);
   }
}