跨线程操作UI
2011-10-18 19:07
316 查看
由于众所周知的原因,一般只有一个线程操作UI。对于多线程程序,怎么让工作线程去操作UI呢?在C++里,可以很方便地利用Windows消息,sendMessage和postMessage。在C#中,MSDN中也给出了用委托的方法。那Java中呢?
Java中观察者模式非常常见。跨线程操作UI也可以用观察者模式来实现。UI线程作为观察者,当工作线程有“动静”时,主动通知UI线程。
被观察的对象“MyAction”通过test方法来通知观察者。MyAction应该在工作线程中。
观察者收到通知时,update方法就会被调用,在这个方法里更新UI即可。
纠错:
这种方法不能实现跨线程操作UI。测试方法,在update方法中获取Thread.currentThread().getId(),发现是非UI线程的ID。看了Observable的代码,确实没有跨线程的内容。
不过下述JComponent方法是安全的,可以从任何线程调用:repaint()、revalidate()、和invalidate()。(repaint()和revalidate()方法为事件派发线程对请求排队,并分别调用paint()和validate()方法。invalidate()方法只在需要确认时标记一个组件和它的所有直接祖先。)所以,可以重写这些方法,来更新UI。
另外,一般也不能使用Timer来主动获取工作线程的数据,因为Timer运行在其它线程上,不过可以参考http://jianshusoft.blog.51cto.com/2380869/764382。
本文出自 “木又寸的技术博客” 博客,请务必保留此出处http://jianshusoft.blog.51cto.com/2380869/691372
Java中观察者模式非常常见。跨线程操作UI也可以用观察者模式来实现。UI线程作为观察者,当工作线程有“动静”时,主动通知UI线程。
import java.util.Observable; import java.util.Observer; public class MyAction extends Observable{ public void test(){ this.setChanged(); this.notifyObservers(); } }
被观察的对象“MyAction”通过test方法来通知观察者。MyAction应该在工作线程中。
public class MainFrame extends JFrame implements Observer { @Override protected void frameInit() { // TODO Auto-generated method stub super.frameInit(); this.setLayout(null); JButton jb = new JButton("test"); jb.setSize(100, 100); jb.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub Thread t = new Thread(){ @Override public void run() { // TODO Auto-generated method stub MyAction action = new MyAction(); //注册观察者 action.addObserver(MainFrame.this); try { this.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } action.test(); } }; t.start(); } }); this.add(jb); } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub MainFrame f = new MainFrame(); f.setVisible(true); f.setDefaultCloseOperation(EXIT_ON_CLOSE); f.setSize(200, 200); } @Override public void update(Observable o, Object arg) { // TODO Auto-generated method stub JOptionPane.showMessageDialog(null, "message"); } }
观察者收到通知时,update方法就会被调用,在这个方法里更新UI即可。
纠错:
这种方法不能实现跨线程操作UI。测试方法,在update方法中获取Thread.currentThread().getId(),发现是非UI线程的ID。看了Observable的代码,确实没有跨线程的内容。
不过下述JComponent方法是安全的,可以从任何线程调用:repaint()、revalidate()、和invalidate()。(repaint()和revalidate()方法为事件派发线程对请求排队,并分别调用paint()和validate()方法。invalidate()方法只在需要确认时标记一个组件和它的所有直接祖先。)所以,可以重写这些方法,来更新UI。
另外,一般也不能使用Timer来主动获取工作线程的数据,因为Timer运行在其它线程上,不过可以参考http://jianshusoft.blog.51cto.com/2380869/764382。
本文出自 “木又寸的技术博客” 博客,请务必保留此出处http://jianshusoft.blog.51cto.com/2380869/691372
相关文章推荐
- 主线程中也不绝对安全的 UI 操作
- 为什么Android的UI操作是线程不安全的
- c#非委托方式在子线程里操作UI控件(实际上运算逻辑在子线程,更新还是在主线程,解决了UI界面无响应的问题)
- 基于接口和队列的线程操作UI方式
- c#中Lock(锁)的研究以及跨线程UI的操作
- [WinForm]WinForm跨线程UI操作常用控件类大全
- 关于子线程里不能更新UI操作的解决方法
- android UI 操作 不要在子线程中操作UI
- Android UI 线程执行操作的三种方式
- android 访问网络不能在主线程中进行以及在线程中操作UI的解决方法
- C# 跨线程操作UI(界面)
- 4种在线程中操作UI的方法
- 主线程不能执行耗时的操作,子线程不能更新Ui
- 工作线程(耗时操作)与UI线程实现异步更新
- wpf调用外部线程操作ui方法
- 为什么必须在主线程中操作UI
- 子线程中进行UI操作
- Android中为什么主线程更新UI,子线程执行耗时操作?
- [WinForm]WinForm跨线程UI操作常用控件类大全
- Winform软件,不要在线程里操作UI