[英]Java - send signal from Thread to Swing component
我想問一下,如果我可以運行Thread,並且是否發生了某些事件,則發送信號,並且某些swing組件將捕獲信號。 像這樣:
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());
}
}
SwingWorker
是一個自包含的“線程”(出於參數考慮),這意味着它將創建並啟動它自己的Thread
從該doInBackground
將調用doInBackground
。
然后, doInBackground
應該“做某事”並使用中間值調用publish
(假設您想在最后生成一個總值,否則,它只會生成一個值)
在未來的某個時刻process
被調用。 在EDT的上下文中調用此方法,從而可以安全地從內部更新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
,該SwingWorker
監視一些全局監視器鎖定,從而允許“主要”工作人員觸發notifyAll
,然后將允許“組件工作人員”發布一些結果...但是如何獲得值!?
在這一點上,我可能只會考慮使用某種事件總線
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.