[英]Make a swing thread that show a “Please Wait” JDialog
問題是這樣的:
我正在運行一個swing應用程序,在某個時刻,對話框需要插入用戶名和密碼並按“確定”。
我希望當用戶按下“ok”時,swing應用程序按此順序執行:
這是我在okButtonActionPerformed()中編寫的代碼:
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {
//This class simply extends a JDialog and contains an image and a jlabel (Please wait)
final WaitDialog waitDialog = new WaitDialog(new javax.swing.JFrame(), false);
waitDialog.setVisible(true);
... //Do some operation (eventually show other JDialogs or JOptionPanes)
waitDialog.dispose()
}
這段代碼顯然不起作用,因為當我在同一個線程中調用waitDialog時,它會阻塞所有代碼直到我不關閉它。
所以我試着在另一個線程中運行它:
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {
//This class simply extends a JDialog and contains an image and a jlabel (Please wait)
final WaitDialog waitDialog = new WaitDialog(new javax.swing.JFrame(), false);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
waitDialog.setVisible(true);
}
});
... //Do some operation (eventually show other JDialogs or JOptionPanes)
waitDialog.dispose()
}
但這也不起作用,因為waitDialog不會立即顯示,但只有在操作完成后才能完成工作(當他們顯示joption窗格時“你以...身份登錄”)
我還嘗試使用invokeAndWait而不是invokeLater,但在這種情況下它會拋出異常:
Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread
我能怎么做?
考慮使用SwingWorker進行后台工作,然后在SwingWorker的done()
方法或(我的首選項)中添加到SwingWorker的PropertyChangeListener中關閉對話框。
例如,
import java.awt.BorderLayout;
import java.awt.Dialog.ModalityType;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
public class PleaseWaitEg {
public static void main(String[] args) {
JButton showWaitBtn = new JButton(new ShowWaitAction("Show Wait Dialog"));
JPanel panel = new JPanel();
panel.add(showWaitBtn);
JFrame frame = new JFrame("Frame");
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class ShowWaitAction extends AbstractAction {
protected static final long SLEEP_TIME = 3 * 1000;
public ShowWaitAction(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent evt) {
SwingWorker<Void, Void> mySwingWorker = new SwingWorker<Void, Void>(){
@Override
protected Void doInBackground() throws Exception {
// mimic some long-running process here...
Thread.sleep(SLEEP_TIME);
return null;
}
};
Window win = SwingUtilities.getWindowAncestor((AbstractButton)evt.getSource());
final JDialog dialog = new JDialog(win, "Dialog", ModalityType.APPLICATION_MODAL);
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("state")) {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
dialog.dispose();
}
}
}
});
mySwingWorker.execute();
JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
JPanel panel = new JPanel(new BorderLayout());
panel.add(progressBar, BorderLayout.CENTER);
panel.add(new JLabel("Please wait......."), BorderLayout.PAGE_START);
dialog.add(panel);
dialog.pack();
dialog.setLocationRelativeTo(win);
dialog.setVisible(true);
}
}
筆記:
public void okButtonActionPerformed(ActionEvent e) {
final JDialog loading = new JDialog(parentComponent);
JPanel p1 = new JPanel(new BorderLayout());
p1.add(new JLabel("Please wait..."), BorderLayout.CENTER);
loading.setUndecorated(true);
loading.getContentPane().add(p1);
loading.pack();
loading.setLocationRelativeTo(parentComponent);
loading.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
loading.setModal(true);
SwingWorker<String, Void> worker = new SwingWorker<String, Void>() {
@Override
protected String doInBackground() throws InterruptedException
/** Execute some operation */
}
@Override
protected void done() {
loading.dispose();
}
};
worker.execute();
loading.setVisible(true);
try {
worker.get();
} catch (Exception e1) {
e1.printStackTrace();
}
}
上述答案的變體
這是一種簡單易行的方式......
//This code goes inside your button action
DialogWait wait = new DialogWait();
SwingWorker<Void, Void> mySwingWorker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
//Here you put your long-running process...
wait.close();
return null;
}
};
mySwingWorker.execute();
wait.makeWait("Test", evt);
//end
//Create this class on your project
class DialogWait {
private JDialog dialog;
public void makeWait(String msg, ActionEvent evt) {
Window win = SwingUtilities.getWindowAncestor((AbstractButton) evt.getSource());
dialog = new JDialog(win, msg, Dialog.ModalityType.APPLICATION_MODAL);
JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
JPanel panel = new JPanel(new BorderLayout());
panel.add(progressBar, BorderLayout.CENTER);
panel.add(new JLabel("Please wait......."), BorderLayout.PAGE_START);
dialog.add(panel);
dialog.pack();
dialog.setLocationRelativeTo(win);
dialog.setVisible(true);
}
public void close() {
dialog.dispose();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.