【发布时间】:2013-09-14 20:59:20
【问题描述】:
如果我理解正确,当我直接从另一个线程修改 Swing 组件时,该操作应该放在 EDT 的事件队列中以防止与 GUI 的同步问题:
public class SwingFrame extends JFrame {
private JTextField _textField;
public SwingFrame() {
_textField = new JTextField();
Thread thread = new Thread(new SomeRunnable(_textField));
thread.start();
}
}
public class SomeRunnable implements Runnable {
private final JTextField _textField;
public SomeRunnable(final JTextField textField) {
_textField = textField;
}
@Override
public void run() {
// _textField.setText("Goodbye, Swing!"); /* wrong */
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
_textField.setText("Hello, Swing!");
}
});
}
}
我的问题是,当 Swing 组件不是在非 EDT 线程中直接修改,而是通过在 EDT 上执行的 PropertyChangeListener 从另一个线程接收 PropertyChangeEvent 时,我是否需要遵循相同的习惯用法?
public class SwingFrame extends JFrame implements PropertyChangeListener {
private JTextField _textField;
public SwingFrame() {
_textField = new JTextField();
Thread thread = new Thread(new SomeRunnable());
thread.start();
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("text")) {
_textField.setText(String.valueOf(evt.getNewValue()));
}
}
}
public class SomeRunnable implements Runnable {
private final PropertyChangeSupport _propertyChangeSupport;
public SomeRunnable() {
_propertyChangeSupport = new PropertyChangeSupport(this);
}
@Override
public void run() {
// Ok? Or wrap in EventQueue.invokeLater()?
_propertyChangeSupport.firePropertyChange("text", null, "Hello, Swing!");
}
}
PropertyChangeSupport 中似乎没有任何东西可以使其本质上“Swing 安全”,但如果不需要的话,我不想通过对 EventQueue.invokeLater() 的不必要调用来混淆我的代码。
【问题讨论】:
-
@nachokk 我能理解你的来历 - 包装直接访问 Swing 组件的代码基本上会使其与第一个示例相同。但我的问题更多地与是否有必要包装 either 调用有关,如果是,为什么或为什么不?
-
我“相信”
setText是您可以在 Swing 中进行的少数线程安全调用之一,但这需要验证。我总是谨慎行事,并在 EDT 内做所有事情,这更容易记住 -
@MadProgrammer 我用
setText作为SSCCE 的例子,没想到,哎呀——我实际上是在尝试举例说明非线程安全的操作。 -
正如我所说的“我相信”,这并不是事实;)
标签: java multithreading swing