当前位置: 首页 > 知识库问答 >
问题:

制作一个显示“Please Wait”JDialog的swing线程

韩寂离
2023-03-14

问题是这样的:
我有一个摆动应用程序正在运行,在某一点上,一个对话框需要插入用户名和密码并按“确定”。
我希望当用户按“确定”时,摆动应用程序按以下顺序执行:

  1. 打开“请稍候”JDialog
  2. 进行一些操作(最终显示一些其他JDialog或JOptionPane)
  3. 操作完成后,关闭“please wait”(请等待)JDialog

这是我在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不会立即显示,而是在操作完成后才显示(当它们显示jption窗格“您以...”)

我还尝试使用invokeAndWait而不是invokeLater,但在这种情况下,它引发了一个异常:

Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread

我该怎么做?

共有3个答案

鲜于璞瑜
2023-03-14

上述答案的变体

这是一种简单且可复制的方法。。。

//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();
   }
}
倪风史
2023-03-14
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();
    }
}
闻人嘉木
2023-03-14

考虑使用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);
   }
}

注意:

  • 一个关键的概念是在显示模式对话框之前设置一切,添加PropertyChangeListener,运行SwingWorker,因为一旦显示了模式对话框,调用代码的所有代码流都将冻结(正如您所发现的)
 类似资料:
  • 问题内容: 我正在使用以下代码在任务栏上显示JDialog,并且在JDK 1.6中可以正常工作。 但是当我使用方法设置模态类型时,它不起作用 这两个代码之间有什么区别?有什么方法可以解决此问题吗? 问题答案: 问题是某些所有者的构造方法会创建一个伪框架所有者(如果所有者是出于历史原因)。但是 必须没有 所有者像顶级窗口一样可见。即 将工作。

  • 我正在用Java Swing开发一个应用程序,有时我需要在这些情况下显示消息: > 当用户点击“添加”按钮时,由于TCP连接,需要较长的时间。我正在使用来显示“processing...”致用户。当用户单击“添加”按钮时,我会更改面板的,其中包含消息。 我想问,这是一个错误的做法吗?它是否会导致性能和可视化问题?我应该使用还是来实现这些过程?

  • 问题内容: 我正在尝试创建两个线程,一个线程显示0到10的偶数整数,一个线程显示1到11的奇数整数。下面的代码是否适合设计该程序? 问题答案: 我只是更改一些细节(无需在此处使用模运算符…):

  • 问题内容: 我在JDialog 的秋千内使用html页面。 在html中, 当鼠标移至链接时,可以通过浏览器查看网页。 当我按下链接时,出现错误“未安装默认邮件客户端”,但是我猜这是由于在我的PC中没有配置Outlook或其他程序。 当从我的Swing应用程序中打开JDialog时,我看到突出显示为链接,但是当我按下链接时,什么也没有发生。 我原本希望得到与浏览器相同的错误消息。 所以我的问题是可

  • 问题内容: 我正在尝试在Windows中显示。如何在Windows任务栏上显示(如)? 问题答案: 对话框本身不能具有任务栏条目,但是您可以构造一个没有任何可见效果的框架,并将其用作对话框的父级。然后,该对话框看起来像具有任务栏条目。以下代码显示了如何执行此操作:

  • 问题内容: 我想在新的JDialog中创建JProgressBar,它将与主逻辑处于不同的线程中。因此,我可以通过仅创建新的JDialog并通过处置JDialog完成该进度来开始不确定的进度。但这给了我很多时间,因为在出​​现JDialog之后,直到完成主线程(SwingUtilities)中的逻辑后,它才显示任何组件(包括JProgressBar)。 包含JDialog的线程: JProgres