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

时间:2015-01-25 16:05:49

标签: java multithreading swing user-interface swingworker

我正在使用swingworker在后台运行一个方法,并定期用信息更新gui,但是从我发现的内容中,不能从另一个类调用。这就是我的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()是不可能的。

1 个答案:

答案 0 :(得分:1)

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

  • 为Navigator提供一个PropertyChangeSupport对象以及一个addPropertyChangeListener(PropertyChangeListener listener)方法,该方法将传入的侦听器添加到支持对象。
  • 给Navigator一些&#34;绑定&#34; property,一个字段,当其状态发生变化时,通常采用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);
   }
}