我在这个类中执行任务,Dialog弹出为白色框。 print语句IS打印出我期望的进度值,但在操作完成之前,Dialog上没有显示任何内容。在结束对话框关闭之前,我可以看到进度条闪烁可见一毫秒。完全不知道发生了什么:\
public class ProgressDialog extends JDialog {
private JProgressBar pb;
private SwingWorker<Boolean, Void> task;
public SwingWorker<Boolean, Void> getTask(){
return task;
}
public ProgressDialog(final String call){
setTitle("Working...");
setLayout(new BorderLayout());
setBounds(300,300,300,100);
pb = new JProgressBar(0, 100);
pb.setValue(0);
pb.setVisible(true);
pb.setStringPainted(true);
add(pb, BorderLayout.CENTER);
setVisible(true);
task = new SwingWorker<Boolean, Void>(){
public Boolean doInBackground(){
switch(call){
case "Category": pb.setValue(Category.getProgress());
while(pb.getValue()<99){
try{
Thread.sleep(500);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
}
pb.setValue(Category.getProgress());
System.out.println(pb.getValue());
repaint();
revalidate();
}
break;
}
return true;
}
public void done(){
dispose();
}
};
}
}
编辑:试过这个改变。没有骰子。为什么我甚至没有获得0%的进度条?只有在100%时才出现
public class ProgressDialog extends JDialog {
private JProgressBar pb;
private SwingWorker<Boolean, Integer> task;
public SwingWorker<Boolean, Integer> getTask(){
return task;
}
public ProgressDialog(final String call){
setTitle("Working...");
setLayout(new BorderLayout());
setBounds(300,300,300,100);
pb = new JProgressBar(0, 100);
pb.setValue(0);
pb.setStringPainted(true);
add(pb, BorderLayout.CENTER);
setVisible(true);
task = new SwingWorker<Boolean, Integer>(){
public Boolean doInBackground(){
switch(call){
case "Category": setProgress(Category.getProgress());
while(pb.getValue()<99){
try{
Thread.sleep(500);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
}
setProgress(Category.getProgress());
}
break;
}
return true;
}
public void done(){
//dispose();
}
};
task.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
System.out.println((Integer)evt.getNewValue());
pb.setValue((Integer)evt.getNewValue());
pb.revalidate();
pb.repaint();
}
}
});
}
}
答案 0 :(得分:3)
您正在尝试从SwingWorker的doInBackground方法中设置进度条的状态,从后台线程 - 这没有任何意义。使用SwingWorker的全部原因是允许您在Swing GUI中执行后台处理,因此您不会从后台线程进行Swing调用,因此您不会将Swing线程与运行一点代码。
您不应该通过此后台进程进行Swing调用。而是使用发布/处理方法,如教程将向您展示的那样。或者更好的是,设置SwingWorker的进度字段,并在SwingWorker上使用PropertyChangeListener以允许进度条对其做出反应。
无论如何,底线:
setBounds(...)
或null布局。相信我是一个写过数百个Swing程序的人,这个程序最终会咬你。答案 1 :(得分:2)
这是一个SSCCE,用于演示如何更新JProgressBar
。复制/粘贴并运行它。
请注意我们如何通过调用publish(i)
来更新进度条,process()
将整数发送到SwingWorker
方法。 process()
以块的形式将结果发送到Integer
方法,但我们只使用JProgressBar
来更新SwingWorker
所以我们关心的是最后一个块。在这个SSCCE中,我们从1-1000开始。如果你检查一下控制台,你会看到很多1-1000之间的数字被跳过,因为我们更新速度太慢而process()
赶上了(但没关系。这就是为什么它以块的形式提供结果的原因)。
注意:JTable
方法最初是为程序员设计的,用于从长时间运行的进程返回实时结果并更新GUI。因此,如果您正在进行数据库提取,则可以使用返回的结果更新JProgressBar
。不过我讨厌这样做。所以99%的时间我只使用“不确定”done()
并等到JProgressBar
方法发布我的结果。然而,偶然地,我将使用“确定的”process()
并像我们在此SSCCE中那样更新。我从未使用import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
/**
*
* @author Ryan
*/
public class Test {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
go();
}
});
}
public static void go() {
JFrame frame = new JFrame();
JProgressBar jpb = new JProgressBar();
jpb.setIndeterminate(false);
int max = 1000;
jpb.setMaximum(max);
frame.add(jpb);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
new Task(jpb, max).execute();
}
static class Task extends SwingWorker<Void, Integer> {
JProgressBar jpb;
int max;
public Task(JProgressBar jpb, int max) {
this.jpb = jpb;
this.max = max;
}
@Override
protected void process(List<Integer> chunks) {
jpb.setValue(chunks.get(chunks.size()-1)); // The last value in this array is all we care about.
System.out.println(chunks.get(chunks.size()-1));
}
@Override
protected Void doInBackground() throws Exception {
for(int i = 0; i < max; i++) {
Thread.sleep(10); // Sleep for 1/10th of a second
publish(i);
}
return null;
}
@Override
protected void done() {
try {
get();
JOptionPane.showMessageDialog(jpb.getParent(), "Success", "Success", JOptionPane.INFORMATION_MESSAGE);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}
}
}
来返回和发布实际数据。 :)但是,这就是最初设计的目的。
SwingWorker
编辑:我创建了一个图表,在处理{{1}}时应该是一个有用的参考,以便您知道代码的放置位置。