我想在新的JDialog中制作JProgressBar,女巫将与主逻辑分开。因此,只需创建新的JDialog并完成处理JDialog的进度,我就可以开始不确定的进步。但它让我很难实现这一点,因为在JDialog出现之后它不显示任何组件(包括JProgressBar),直到主线程(SwingUtilities)中的逻辑完成。
线程包括JDialog:
package gui.progress;
public class ProgressThread extends Thread {
private ProgressBar progressBar = null;
public ProgressThread() {
super();
}
@Override
public void run() {
progressBar = new ProgressBar(null);
progressBar.setVisible(true);
}
public void stopThread() {
progressBar.dispose();
}
}
JProgressBar切换方法:
private static ProgressThread progressThread = null;
...
public static void toggleProcessBar() {
if(progressThread == null) {
progressThread = new ProgressThread();
progressThread.start();
} else {
progressThread.stopThread();
progressThread = null;
}
}
答案 0 :(得分:8)
但它让我很难实现这一点,因为在JDialog出现之后它不显示任何组件(包括JProgressBar),直到主线程(SwingUtilities)中的逻辑完成。
您遇到Concurrency in Swing问题,Swing是单线程的,所有更新必须在EventDispatchThread完成,有两种方式
易于使用Runnable#Thread
,但输出到Swing GUI必须包含在invokeLater
使用SwingWorker,关于SwingWorker
的示例位于Oracles JProgressBar和SwingWorker教程
编辑
此代码模拟违反EDT并正确解决SwingWorker的解决方法
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
public class TestProgressBar {
private static void createAndShowUI() {
JFrame frame = new JFrame("TestProgressBar");
frame.getContentPane().add(new TestPBGui().getMainPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowUI();
}
});
}
private TestProgressBar() {
}
}
class TestPBGui {
private JPanel mainPanel = new JPanel();
public TestPBGui() {
JButton yourAttempt = new JButton("Your attempt to show Progress Bar");
JButton myAttempt = new JButton("My attempt to show Progress Bar");
yourAttempt.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
yourAttemptActionPerformed();
}
});
myAttempt.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
myAttemptActionPerformed();
}
});
mainPanel.add(yourAttempt);
mainPanel.add(myAttempt);
}
private void yourAttemptActionPerformed() {
Window thisWin = SwingUtilities.getWindowAncestor(mainPanel);
JDialog progressDialog = new JDialog(thisWin, "Uploading...");
JPanel contentPane = new JPanel();
contentPane.setPreferredSize(new Dimension(300, 100));
JProgressBar bar = new JProgressBar(0, 100);
bar.setIndeterminate(true);
contentPane.add(bar);
progressDialog.setContentPane(contentPane);
progressDialog.pack();
progressDialog.setLocationRelativeTo(null);
Task task = new Task("Your attempt");
task.execute();
progressDialog.setVisible(true);
while (!task.isDone()) {
}
progressDialog.dispose();
}
private void myAttemptActionPerformed() {
Window thisWin = SwingUtilities.getWindowAncestor(mainPanel);
final JDialog progressDialog = new JDialog(thisWin, "Uploading...");
JPanel contentPane = new JPanel();
contentPane.setPreferredSize(new Dimension(300, 100));
final JProgressBar bar = new JProgressBar(0, 100);
bar.setIndeterminate(true);
contentPane.add(bar);
progressDialog.setContentPane(contentPane);
progressDialog.pack();
progressDialog.setLocationRelativeTo(null);
final Task task = new Task("My attempt");
task.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equalsIgnoreCase("progress")) {
int progress = task.getProgress();
if (progress == 0) {
bar.setIndeterminate(true);
} else {
bar.setIndeterminate(false);
bar.setValue(progress);
progressDialog.dispose();
}
}
}
});
task.execute();
progressDialog.setVisible(true);
}
public JPanel getMainPanel() {
return mainPanel;
}
}
class Task extends SwingWorker<Void, Void> {
private static final long SLEEP_TIME = 4000;
private String text;
public Task(String text) {
this.text = text;
}
@Override
public Void doInBackground() {
setProgress(0);
try {
Thread.sleep(SLEEP_TIME);// imitate a long-running task
} catch (InterruptedException e) {
}
setProgress(100);
return null;
}
@Override
public void done() {
System.out.println(text + " is done");
Toolkit.getDefaultToolkit().beep();
}
}
答案 1 :(得分:1)
在主线程中显示进度条(所有挥杆内容都在哪里),并在单独的线程上进行密集的后台工作。
UI将始终响应(因为您不阻止主线程),并且您可以在长时间运行的任务完成时通知它。