Java:mytextarea.setText(";hello";)&x2B;线程睡眠(1000)=奇怪的结果
我有这样的想法:Java:mytextarea.setText(";hello";)&x2B;线程睡眠(1000)=奇怪的结果,java,user-interface,multithreading,Java,User Interface,Multithreading,我有这样的想法: for(int i=0; i<5; i++){ mytextarea.setText("hello " + i); try{ Thread.currentThread().sleep(1000); //to give time for users to read } catch(Exception e){} } for(inti=0;iYes-您基本上阻塞了UI线程,因此它永远不会真正更新 在UI线程中睡觉真是个坏主意。 如果你想
for(int i=0; i<5; i++){
mytextarea.setText("hello " + i);
try{
Thread.currentThread().sleep(1000); //to give time for users to read
} catch(Exception e){}
}
for(inti=0;iYes-您基本上阻塞了UI线程,因此它永远不会真正更新
在UI线程中睡觉真是个坏主意。
如果你想做这样的事情,你应该使用。(我假设你使用的是Swing。如果不是,请编辑你的问题,指出你使用的是哪个UI框架。)
您还应该注意,Thread.sleep
是一个静态方法。您使用它就像使用实例方法一样。诚然,您碰巧在当前线程上调用它,但您的用法表明您认为:
Thread t = new Thread(...);
t.start();
t.sleep(1000);
将使新线程睡眠。它不会-它将使当前线程睡眠,因为这是thread.sleep
总是做的。在我看来,Java允许您以这种方式调用静态方法是一个错误-如果您使用Eclipse,则有一个选项可以将此设置为警告或错误。当您编写代码时,没有事件等待我们会处理的
阅读javax.swing.SwingUtilities.invokeAndWait()和invokeLater()的javadoc,这可能会有所帮助
编辑:感谢Jon和Samuel将所有想法整合在一起:
public class Swing extends JPanel {
JTextField textField;
static JTextArea textArea;
static int line = 1;
public Swing() {
super(new BorderLayout());
textArea = new JTextArea(5, 20);
add(textArea);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("TextDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Swing());
frame.pack();
frame.setVisible(true);
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
textArea.append("Hello " + line++ + "\n");
}
};
if (line < 5) {
new Timer(1000, taskPerformer).start();
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
公共类Swing扩展了JPanel{
JTextField-textField;
静态JTextArea textArea;
静态整数线=1;
公众秋千{
超级(新边框布局());
textArea=新的JTextArea(5,20);
添加(文本区域);
}
私有静态void createAndShowGUI(){
JFrame=newJFrame(“TextDemo”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(新Swing());
frame.pack();
frame.setVisible(true);
ActionListener taskPerformer=新建ActionListener(){
已执行的公共无效操作(操作事件evt){
textArea.append(“Hello”+line++“\n”);
}
};
如果(第5行){
新计时器(1000,taskPerformer).start();
}
}
公共静态void main(字符串[]args){
javax.swing.SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGUI();
}
});
}
}
正如Jon Skeet在回答中所解释的那样,您应该使用计时器,因为您不能阻止EDT并期望UI更新。下面是重写为使用Swing计时器的示例代码段
ActionListener action = new ActionListener() {
int i = 0;
public void actionPerfomed(ActionEvent e) {
mytextarea.setText("hello " + i++);
}
};
new javax.swing.Timer(1000, action).start();
有关计时器功能的更多信息,请参阅Swing教程中的。另一种不阻止(EDT)的方法是启动新线程:
Thread thread = new Thread(new Runnable() {
@Override
public void runt() {
for (int i=0; i<5; i++) {
mytextarea.setText("hello " + i);
try {
Thread.sleep(1000); //to give time for users to read
} catch (InterruptedException e) {
break; // interrupt the for
}
}
}
});
thread.start();
Thread-Thread=新线程(new Runnable()){
@凌驾
公共空间小矮人(){
对于(int i=0;我会小心地使用这种方法只调用线程安全的方法。JTextComponent.setText是线程安全的,尽管大多数Swing方法都不是。sleep
是一种静态方法。最好使用thread.sleep(…)
而不是thread.currentThread().sleep(…)
。不过这两种方法在语法上都是正确的。