所以我正在尝试学习如何使用线程,所以我决定制作一个程序,添加一个然后等待1/2秒。而线程(我认为我做的正确)刷新了进度条的值。所以我不确定我是否让程序错了,或者它是否被某个地方卡住了。所以我在线程中放了println
,这就是我得到的:
thred
0
1
2
3
4
5
6
7
8
9
10
11 (ect...)
这是我的框架代码:
import java.awt.EventQueue;
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.JProgressBar;
import javax.swing.border.EmptyBorder;
public class frame extends JFrame implements ActionListener{
private static final long serialVersionUID = 1L;
private JPanel contentPane;
public static void main(String[] args) {
frame f = new frame();
f.setVisible(true);
f.setSize(450,120);
}
/**
* Create the frame.
*/
public JProgressBar bar;
public frame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 449, 120);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
bar = new JProgressBar();
bar.setStringPainted(true);
bar.setBounds(6, 50, 438, 32);
contentPane.add(bar);
JLabel lblNewLabel = new JLabel(
"Percent of for loop completion");
lblNewLabel.setBounds(6, 6, 279, 16);
contentPane.add(lblNewLabel);
JButton btnStart = new JButton("START");
btnStart.setBounds(327, 1, 117, 29);
btnStart.addActionListener(this);
contentPane.add(btnStart);
}
public int i, progress;
public void actionPerformed(ActionEvent e) {
updater u = new updater();
u.start();
for( i =0; i < 100; i++){
progress = i;
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(i);
}
}
}
这就是我认为的线程类:
public class updater extends Thread {
public void run() {
System.out.println("thred");
frame f = new frame();
int p = f.progress;
while (p != 100) {
f.bar.setValue(p);
}
}
}
答案 0 :(得分:1)
您正在阻止事件调度线程。除其他事项外,这还负责处理油漆更新。当您阻止该线程时,无法进行更新,这意味着您的程序看起来已经停滞不前......
public void actionPerformed(ActionEvent e) {
updater u = new updater();
u.start();
// Now blocking, no more repaints or event notifications until you finish...
for( i =0; i < 100; i++){
progress = i;
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(i);
}
}
你遇到的另一个问题是Swing(大多数情况下)不是线程安全的。也就是说,预计所有与UI的更新和交互都只能在EDT的上下文中进行。
虽然有很多方法可以解决它,但最简单的方法是使用SwingWorker
,它旨在允许您在后台线程中执行代码并将更新重新同步回UI安全。
看看......
举个例子。
您可能还需要查看Concurrency in Swing了解更多详情
答案 1 :(得分:0)
使用线程进行UI编程很棘手,如果多个线程试图同时修改UI元素,最终可能会出现严重问题。在Swing应用程序中,UI的所有更新都应该在Swing / AWT事件线程上进行。通常的做法是使用EventQueue#invokeLater
来安排Runnable
在线程上执行;在这种情况下,您将f.bar.setValue(p);
包裹在Runnable
中并将其传递给invokeLater
。这里的
a useful tutorial关于事件线程的基础知识。