SwingWorker在后台工作时对话框无响应 [英] Dialog isn't responsive while SwingWorker works in the background
问题描述
基本上,我得到了一个以主要方法为入口点的JFrame.在这种主要方法中,程序必须下载一些图像.
Basically I got a JFrame with a main method as entry point. In this main method the program has to download some images.
为了通知用户该程序将在任何时候启动,我想显示一个简单的对话框.
To inform the user that the program is going to start any minute I want to display a simple dialog.
如果将对话框设置为模式对话框.启动程序以触发下载后,我必须关闭它.
If I set the dialog to modal. I got to close it after starting the program to trigger the download.
如果我将其设置为非模态,它将显示下载时的对话框,但这并不具有响应性.该对话框甚至不再画我的JLabel说请稍候...".
If I set it to non-modal it displays the dialog for the time of the download, but it's not repsonsive. The dialog doesn't even paint my JLabel saying "Please wait..." anymore.
//...
public static void main(String args[])
{
java.awt.EventQueue.invokeLater
(
new Runnable()
{
@Override
public void run()
{
ImageLoadingWorker ilw = new ImageLoadingWorker();
ilw.execute();
new MainFrame().setVisible(true);
}
}
);
}
static class ImageLoadingWorker extends SwingWorker<Void, Void>
{
JDialog dialog ;
public ImageLoadingWorker()
{
dialog = new ImageLoadingDialog(null, false);
dialog.setVisible(true);
}
@Override
protected Void doInBackground()
{
ImageLoading.getInstance() ; // download is triggered
return null;
}
@Override
protected void done()
{
dialog.dispose() ;
}
}
//...
推荐答案
我认为解决方案很简单:您需要先启动SwingWorker下载,然后显示 modal 对话框.
I believe that the solution is easy: You need to start your download, your SwingWorker, first, and then show the modal dialog.
即
public static void main(String args[])
{
java.awt.EventQueue.invokeLater
(
new Runnable()
{
@Override
public void run()
{
ImageLoadingWorker ilw = new ImageLoadingWorker();
// add a PropertyChangeListener to the SwingWorker
// when the PCL tells you that the SwingWorker is done, show the mainFrame.
ilw.execute();
// .... code for showing the dialog is here.
// new MainFrame().setVisible(true); // done in PCL
}
}
);
}
更具体的示例:
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
public class SwingWorkerEg {
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
// first set everything up
final MainFrame mainFrame = new MainFrame();
final SomeDialog someDialog = new SomeDialog(mainFrame);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
someDialog.pack();
someDialog.setLocationRelativeTo(null);
// create SwingWorker and its PropertyChangeListener
ImageLoadingWorker ilw = new ImageLoadingWorker();
ilw.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
// since SwingWorker.StateValue is an enum, can use ==
if (SwingWorker.StateValue.DONE == pcEvt.getNewValue()) {
// when *done*, get rid of dialog, and show main JFrame
someDialog.setVisible(false);
mainFrame.setVisible(true);
}
}
});
// first start SwingWorker
ilw.execute();
// And only *after* starting the SW, show the modal dialog
someDialog.setVisible(true);
}
});
}
}
class ImageLoadingWorker extends SwingWorker<Void, Void> {
private static final long SLEEP_TIME = 5 * 1000;
@Override
protected Void doInBackground() throws Exception {
// simulate long-running process
Thread.sleep(SLEEP_TIME);
return null;
}
}
// bad example -- shouldn't extend JDialog!
class SomeDialog extends JDialog {
private static final int PREF_W = 300;
private static final int PREF_H = 60;
public SomeDialog(JFrame frame) {
super(frame, "Some Dialog", ModalityType.APPLICATION_MODAL);
JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
add(progressBar);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
}
// bad example -- shouldn't extend JFrame!
class MainFrame extends JFrame {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
public MainFrame() {
super("Main Frame");
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
}
请记住, 从不 在 doInBackground()
中创建或显示对话框.这不在Swing事件线程中,并且该方法中不能包含任何Swing GUI代码.
Remember, never create or display the dialog in doInBackground()
. That's off the Swing event thread, and no Swing GUI code can go in that method.
这篇关于SwingWorker在后台工作时对话框无响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!