如果我有一个实现JFrame
接口的Observer
,那么会在事件派发线程上执行update()
方法吗?
public class MyFrame extends JFrame implements Observer{
@Override
public void update(Observable o, Object arg) {
//do gui stuff
}
}
public class MyTask extends Observable implements Runnable{
@Override
public void run() {
setChanged();
notifyObservers("Update!");
}
}
答案 0 :(得分:2)
正如我刚才发现的那样:
不,它将在调用Thread
方法的notifyObservers()
上执行。
从源代码中可以看到notifyObservers()
方法,它只是调用观察者的update()
方法,而不将任务传递给另一个线程。
public void notifyObservers(Object arg) {
/*
* a temporary array buffer, used as a snapshot of the state of
* current Observers.
*/
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
}
答案 1 :(得分:0)
如果你想做我认为你想做的事情,你可以使用SwingWorker。它有一个发布方法和处理方法。 publish方法将消息发送到process方法。与其他SwingWorker不同,该过程方法在EDT上运行。
import java.awt.EventQueue;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.List;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
public class MyFrame extends JFrame {
private static JTextField txtFld;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
new UpdateSwingWorker().execute();
}
});
}
private static void createAndShowGUI() {
MyFrame frame = new MyFrame();
JPanel panel = new JPanel(new BorderLayout());
txtFld = new JTextField();
panel.add(txtFld, BorderLayout.CENTER);
frame.setSize(new Dimension(300,200));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(300,200));
frame.setLayout(new BorderLayout());
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private static class UpdateSwingWorker extends SwingWorker<Void, String> {
@Override
protected Void doInBackground() throws Exception {
// Do your work...
System.out.println("Thread in doInBackground: " + Thread.currentThread());
publish("Updated");
return null;
}
@Override
protected void process(List<String> chunks) {
System.out.println("Thread in process: " + Thread.currentThread());
txtFld.setText(chunks != null ? chunks.get(0) : "");
}
}
}
或者,如果您真的想使用Observer模式,可以在EventQueue的invokeLater调用中包装notifyObservers调用。此方法导致Runnable在EDT中执行其run方法。
框:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class MyFrame2 extends JFrame implements Observer {
private static JTextField txtFld;
private static MyTask task = new MyTask();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
new Thread(task).start();
}
});
}
private static void createAndShowGUI() {
MyFrame2 frame = new MyFrame2();
task.addObserver(frame);
JPanel panel = new JPanel(new BorderLayout());
txtFld = new JTextField();
panel.add(txtFld, BorderLayout.CENTER);
frame.setSize(new Dimension(300,200));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(300,200));
frame.setLayout(new BorderLayout());
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
@Override
public void update(Observable o, Object arg) {
System.out.println("Thread in update: " + Thread.currentThread());
txtFld.setText((String) arg);
}
}
任务:
import java.awt.EventQueue;
import java.util.Observable;
public class MyTask extends Observable implements Runnable {
@Override
public void run() {
// Do work
System.out.println("Thread in run: " + Thread.currentThread());
setChanged();
// Notify the observers on the EDT.
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("Thread in invokeLater: " + Thread.currentThread());
notifyObservers("Update!");
}
});
}
}