笔者swing初学,不是很清楚,学习中遇到一个问题,如下。
一个窗体(JFrame),窗体上有两个控件,其中一个JButton,一个JLabel,想要实现的效果是,点击button,label显示从0递增到9,每秒递增一次。
想当然地在button的点击事件中
for(int i = 0 ; i < 10 ; i ++){
Thread.sleep(1000);
label.setText(i + "");
}
但是运行处来的效果是:点击button,label上的文字不变(初始文字),直到最后一次调用setText()函数时,label显示10;
开发环境为intelliJ idea , 其中界面设计使用idea的UIdesigner实现。
针对 @brayden 的答案,问题已经解决。
此问题应该是swing编程中基础而且不可回避的,所以针对此做了一个总结:
http://www.yanwushu.com/post/9.html
这个问题我也碰到过,有个updateUI()方法,可以解决。
java swing中两大原则:
1. 不要阻塞UI线程
2. 不要在UI线程外的线程去操作UI控件
button的点击事件 在UI线程中被执行, 这时候去sleep UI线程, 你当然看不到更新了.
下面是一个可以工作的例子:
package com.test.loader;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class LabelDemo extends JPanel implements ActionListener{
private static final long serialVersionUID = 1L;
private JLabel label2;
public LabelDemo() {
super(new GridLayout(2,1));
JButton b1 = new JButton("click me");
b1.addActionListener(this);
label2 = new JLabel("Label");
add(label2);
add(b1);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("LabelDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new LabelDemo());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
new Thread(new Runnable(){
@Override
public void run() {
for(int i = 0 ; i < 10 ; i ++){
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {}
final int x =i;
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
label2.setText(x + "");
}
});
}
}
}).start();
}
}
最后说, 把java tutorial的这一节好好看一下, 非常有用:
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
这个难道不报错?setText(String text)