Java - 从Thread向Swing组件发送信号

时间:2018-04-02 08:06:49

标签: java multithreading swing signals

我想问一下,如果我可以运行Thread,如果发生某些事件,发送信号和一些摆动组件将捕获信号。 像这样:

public class MyThread extends Thread {
  String today = "???";

  @Override
  public void run() {
    if (today.equals("monday")) {
        // send signal
    }
  }
}

public class MyPanel extends JPanel {
  // catching signals and if signal is catched change background color
}

编辑: 我试过这个,但它不起作用。

public class MyThread extends Thread {
@Override
public void run() {
    SwingWorker worker = new SwingWorker<String, String>() {
        @Override
        protected String doInBackground() throws Exception {
            System.out.println("doInBackground");
            publish("doInBackgroundPublish");
            firePropertyChange("firePropertyChange1", "oldValue1", "newValue1");
            return "doInBackground return";
        }
        @Override
        protected void process(List<String> chunks) {
            super.process(chunks);
            firePropertyChange("firePropertyChange2", "oldValue2", "newValue2");
        }
    };
    worker.execute();
}

}

public class MyPanel extends JPanel {
public class SWListen implements PropertyChangeListener, Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("SWListen update");
    }
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println("SWListen propertyChange");
    }
}
public MyPanel {
    addPropertyChangeListener(new SWListen());
}

}

1 个答案:

答案 0 :(得分:2)

SwingWorker是一个自包含的“线程”(为了论证),这意味着它将创建并启动它自己的ThreaddoInBackground将被调用。

然后

doInBackground应“做某事”并使用中间值调用publish(假设您希望在结尾处生成一个整体值,否则,它只会生成一个值)

将来某个时候会调用process。在EDT的上下文中调用此方法,从而可以安全地从内部更新UI。

您可以通过多种方式“通知”更改的UI,大多数都属于“观察者模式”的类别。

例如......

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            JLabel label = new JLabel("...");
            add(label);

            TickerWorker worker = new TickerWorker();
            worker.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    System.out.println(evt.getPropertyName());
                    if ("counter".equals(evt.getPropertyName())) {
                        long value = (long) evt.getNewValue();
                        label.setText(Long.toString(value));
                    }
                }
            });
            worker.execute();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public class TickerWorker extends SwingWorker<Void, Long> {

        @Override
        protected Void doInBackground() throws Exception {
            long counter = 0;
            while (true) {
                Thread.sleep(1000);
                publish(++counter);
            }
        }

        @Override
        protected void process(List<Long> chunks) {
            // Since we're in the EDT, it's probably pointless do announce ALL the
            // values, we're probably only interested in the last one
            for (long value : chunks) {
                firePropertyChange("counter", value - 1, value);
            }
        }
    }

}

现在,这会通知单个组件,如果您需要通知多个组件,那么它就会变得更加困难。

你可以让每个组件创建它自己的SwingWorker,它监视一些全局监视器锁,允许“主”工作者触发notifyAll,然后允许“组件工作者”发布一些结果...但你怎么得到价值!?

此时我可能只考虑使用某种event bus