JProgressBar在新线程JDialog中 [英] JProgressBar in new thread JDialog
问题描述
我想在新的JDialog中制作JProgressBar,女巫将与主逻辑分开。因此,我可以通过创建新的JDialog并在处理JDialog时完成这一进步来开始不确定的进展。但它让我很难实现这一点,因为在JDialog出现之后它不显示任何组件(包括JProgressBar),直到主线程(SwingUtilities)中的逻辑完成。
I would like to make JProgressBar in new JDialog, witch will be in separate thread from main logic. So I can start indeterminate progress with just creating new JDialog and completing that progress with disposing JDialog. But it gives me hard time to achieve that because after JDialog appears it doesn't show any components (including JProgressBar) until the logic in main thread (SwingUtilities) is done.
线程包括JDialog:
Thread including 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切换方法:
JProgressBar toggle method:
private static ProgressThread progressThread = null;
...
public static void toggleProcessBar() {
if(progressThread == null) {
progressThread = new ProgressThread();
progressThread.start();
} else {
progressThread.stopThread();
progressThread = null;
}
}
推荐答案
但它让我很难实现这一点,因为在JDialog出现之后它不会显示任何组件(包括JProgressBar),直到主线程(SwingUtilities)中的逻辑完成。
But it gives me hard time to achieve that because after JDialog appears it doesn't show any components (including JProgressBar) until the logic in main thread (SwingUtilities) is done.
您遇到 Swing中的并发问题,Swing是单线程的,所有更新必须在 EventDispatchThread 上完成,有两种方法
you have issue with Concurrency in Swing, Swing is single threaded and all updates must be done on EventDispatchThread, there are two ways
-
易于使用
Runnable #Thread
,但是输出到Swing GUI必须包装到invokeLater
easies to use
Runnable#Thread
, but output to the Swing GUI must be wrapped intoinvokeLater
使用SwingWorker ,关于 SwingWorker
的示例位于Oracles JProgressBar 和 SwingWorker 教程
use SwingWorker, example about SwingWorker
is in the Oracles JProgressBar and SwingWorker tutorial
编辑
此代码模拟违反EDT并为SwingWorker更正解决方法
this code simulate violating EDT and correct workaround for SwingWorker too
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();
}
}
这篇关于JProgressBar在新线程JDialog中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!