带线程的进度条(Java Swing)
这里有一个小例子:带线程的进度条(Java Swing),java,swing,thread-sleep,Java,Swing,Thread Sleep,这里有一个小例子: private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { int x = 0; while (jProgressBar1.getValue() < 100) { try { Thread.sleep(50);
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
int x = 0;
while (jProgressBar1.getValue() < 100) {
try {
Thread.sleep(50);
x++;
jProgressBar1.setValue(x);
jProgressBar1.repaint();
} catch (InterruptedException ex) {
Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(jProgressBar1.getValue());
}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){
int x=0;
while(jProgressBar1.getValue()<100){
试一试{
睡眠(50);
x++;
jProgressBar1.设定值(x);
jProgressBar1.repaint();
}捕获(中断异常例外){
Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE,null,ex);
}
System.out.println(jProgressBar1.getValue());
}
}
System.out.println(jProgressBar1.getValue())代码>将数字返回到IDE输出,但jProgressBar1不绘制此值。这个代码怎么了?请帮忙 问题在于,您在执行“工作”(thread.sleep)的同一线程中调用了.repaint()
。这意味着您正在安排一系列repaint()
调用,但它们没有被处理。我还敢打赌,一旦值达到100,进度条就会跳到满状态,这是因为主线程已经结束,所有的repaint()
调用最终都在处理中
为了使jProgressBars工作,您必须让它们的重新绘制发生在与您正在工作的线程不同的线程中(值得注意的是,它也应该在不同的线程中-对于大多数Swing更新也是如此)。在调用代码之前,请尝试在新线程中启动此Runnable:
public class ProgressBarPainter implements Runnable{
public JProgressBar jProgressBar1;
public void run(){
while(true){
try {
Thread.sleep(50);
jProgressBar1.repaint();
} catch (InterruptedException ex) {
break;
}
}
}
}
示例使用上述功能的代码:
public class Frame extends JFrame {
private static final long serialVersionUID = 1L;
private JProgressBar bar;
public Frame(){
JPanel contentPanel = (JPanel) getContentPane();
JButton b = new JButton("Do Process");
b.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
ProgressBarPainter p = new ProgressBarPainter();
p.jProgressBar1 = bar; //Fill in with the bar you want painted
Thread t = new Thread(p);
t.start();
Worker w = new Worker();
w.jProgressBar1 = bar;
Thread t2 = new Thread(w);
t2.start();
}
});
contentPanel.add(b, BorderLayout.SOUTH);
bar = new JProgressBar();
contentPanel.add(bar, BorderLayout.CENTER);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new Frame();
}
}
class Worker implements Runnable{
public JProgressBar jProgressBar1;
public void run(){
int x = 0;
while(jProgressBar1.getValue() != jProgressBar1.getMaximum()){
try {
//Do some work
Thread.sleep(50);
//Update bar
jProgressBar1.setValue(x++);
} catch (InterruptedException ex) {
break;
}
}
}
}
class ProgressBarPainter implements Runnable{
public JProgressBar jProgressBar1;
public void run(){
while(true){
try {
Thread.sleep(50);
jProgressBar1.repaint();
} catch (InterruptedException ex) {
break;
}
}
}
}
不要在Swing线程中使用Thread.sleep()。改用javax.swing.Timer
例如:
private void jButton1ActionPerformed(ActionEvent evt) {
final Timer t = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
jProgressBar1.setValue(jProgressBar1.getValue() + 1);
if (jProgressBar1.getValue() == 100) {
((Timer) e.getSource()).stop();
}
}
});
t.start();
}
不管怎么说,没有它是不行的。。。我认为线程有问题。我用另一个代码测试了它:intvalues[]={1,5,9,20,22,25,45,50,55,70,80,90,99100}
for(int-value:values){try{Thread.sleep(50);}catch(InterruptedException ex){Logger.getLogger(MainWindow.class.getName())..}`jProgressBar1.setValue(value);}}不使用Thread.sleep()
因为它将冻结Swing应用程序。相反,您应该使用javax.swing.Timer
。尝试使用SwingWorker
我提供了一个示例,说明了它应该如何实现。是的,它可以工作,但它可以很快地填充progressbar。如何更改dalay?@alexkowalski这是计时器构造函数的第一个参数。将第二行更改为:final Timer t=new Timer(250,new ActionListener(){这没有帮助!不是1000不是10000…什么都没有发生,只是填充速度非常快而已。