精通Swing的来指教下

pwl2014 2010-03-30 04:01:48
看了网上的资料,对于 SwingUtilities.invokeLater() 的用法还是不解。
我在 actionPerformed() 方法中新起一个线程去做事情并更新组件的状态,与使用 SwingUtilities.invokeLater() 有什么不同?我自己写了个例子,一个button 和一个progressbar,点button,progressbar开始更新,发现两种方法实现的效果是一样的,网上看到说,在新起一个线程中更新组件状态是不安全的,不安全在哪里呢?
...全文
119 9 打赏 收藏 转发到动态 举报
写回复
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
pwl2014 2010-03-30
  • 打赏
  • 举报
回复
都没有说到点子上去,从Sun的论坛上找到了答案和大家分享下,自己也写过例子证实了:
”I was calling JLabel.setText from a thread that wasn't EDT“
Agreed it doesn't seem like a big deal because the setText() method simply saves the text in a class variable and invokes repaint(). According to the article repaint() is thread safe.

However, the setText() method also creates a PropertyChangeEvent. So if you have a listener that does something with the property change event it won't be executing on the EDT, so I guess you could have a problem.

后半段是重点,自己 new 一个 Thread 并简单的在里面更新组件状态是不安全的。
Wuerselen 2010-03-30
  • 打赏
  • 举报
回复
建议使用线程管理,当执行按钮中的线程时,将按钮disabled。
线程中执行任务,执行完毕后,将按钮enabled。
bayougeng 2010-03-30
  • 打赏
  • 举报
回复
我好像讲错了,我讲的那个,必须手动new 一个Thread才行。像这样:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Calendar extends JFrame implements ActionListener {

private JButton button_ok = new JButton("Click me.");

public Calendar() {
super();
this.setTitle("TEST");
this.setLocation(500, 300);
this.setResizable(true);
button_ok.addActionListener(this);
getContentPane().add(button_ok);
pack();
}

public void actionPerformed(ActionEvent e) {

new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getId());
}
}).start();

// try {
// Thread.sleep(3000);
// } catch (InterruptedException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// }
}

public static void main(String[] args) {
System.out.println(Thread.currentThread().getId());
Calendar CT = new Calendar();
CT.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CT.setVisible(true);
}
}
actionPerformed方法稍加改动你就能看见效果。
在事件分派线程中,SwingUtilities.invokeLater()还是会阻塞当前线程。
pwl2014 2010-03-30
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 bayougeng 的回复:]

你可以自己试试嘛,在按钮点击的action方法中搞个sleep,然后看看是什么情况。
然后换成SwingUtilities.invokeLater()的方式,看有什么区别。
[/Quote]

我有说过在 actionPerformed()中进行费时的操作吗??
bayougeng 2010-03-30
  • 打赏
  • 举报
回复
你可以自己试试嘛,在按钮点击的action方法中搞个sleep,然后看看是什么情况。
然后换成SwingUtilities.invokeLater()的方式,看有什么区别。
bayougeng 2010-03-30
  • 打赏
  • 举报
回复
比如,有时候点了一个按钮后,你会做一件比较复杂费时的操作。
如果你在当前线程里做,则按钮就一直是沉下状态,直到你的事情办完。按钮弹起之前,界面会失去响应。
如果你用SwingUtilities.invokeLater()的方式,则点完之后按钮直接就弹起来了。这项费时的操作将在后台进行。这是ui设计中非常常用的方法。
pwl2014 2010-03-30
  • 打赏
  • 举报
回复
我就是不明白"界面绘制错误"是如何发生的?能写个例子出来:用 SwingUtilities.invokeLater() 就 work,不用就出错?
铁匠梁老师 2010-03-30
  • 打赏
  • 举报
回复
涉及到界面上的绘制,最好放在SwingUtilities.invokeLater() 方法中来执行,避免界面绘制错误
pwl2014 2010-03-30
  • 打赏
  • 举报
回复
没人知道??

62,567

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告