java - 创建 'loading...' 动画帧以在执行方法时显示?

标签 java swing concurrency jframe loading

我有一个带有 GUI 的 FileFinder.java 和 Loading.java 类。 FileFinder.java 允许用户选择一个目录并在该目录中搜索文件。现在,对于更大的目录,搜索需要一些时间才能完成,并且我不希望用户怀疑它是否真的在搜索,因此我尝试显示另一个框架(Loading.java)。

这是我单击“搜索”按钮时的代码:

 private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:

        String dirName = "";
        String username = System.getProperty("user.name");

        if(cdriveButton.isSelected()){
            dirName = "C:/Users/" + username;
        }
        else if(pdriveButton.isSelected()){
            dirName = "P:";
        }
        else if(xdriveButton.isSelected()){
            dirName = "X:";
        }
        else if(customButton.isSelected()){
            dirName = JOptionPane.showInputDialog(rootPane, "Enter the directory you would like to search in: ", "Enter Directory", HEIGHT);           
        }   

          String search = filenameText.getText();
          File root = new File(dirName);
          resultText.setText("");


        Loading show = new Loading();

        show.setVisible(true);

        displayDirectoryContents(root, search);

        show.setVisible(false);



    }                 

这是Loading.java:

public class Loading extends javax.swing.JFrame {

    /**
     * Creates new form Loading
     */
    public Loading() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jLabel1.setText("Please wait...");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(148, 148, 148)
                .addComponent(jLabel1)
                .addContainerGap(186, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(122, 122, 122)
                .addComponent(jLabel1)
                .addContainerGap(164, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Loading.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Loading.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Loading.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Loading.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Loading().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JLabel jLabel1;
    // End of variables declaration                   
}

一切正常,除了一个小问题:它没有在加载框架内正确显示 GUI。当我按下按钮时,它会弹出,并保持在那里,直到搜索完成,并正确关闭,但它应该显示一个标签,上面写着“请稍候...”。它没有显示该标签,只是显示一个空白的白框。

Edit1:下面找到解决方案。转换为 JDialog Pane 而不是 JFrame 并添加 SwingWorker:

        JDialog jDialog = new JDialog();
        jDialog.setLayout(new GridBagLayout());
        jDialog.add(new JLabel("Please wait..."));
        jDialog.setMinimumSize(new Dimension(150, 50));
        jDialog.setResizable(false);
        jDialog.setModal(false);
        jDialog.setUndecorated(true);
        jDialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        jDialog.setLocationRelativeTo(null);
        jDialog.setVisible(true);

       SwingWorker swingWorker = new SwingWorker<Void, Void>() {
    @Override
    protected Void doInBackground() throws Exception {
        displayDirectoryContents(root, search);
        return null;
    }
};

最佳答案

您的问题在这里:

displayDirectoryContents(root, search);

您正在 Java 事件线程或 EDT(事件调度线程)上运行它。当运行时间超过一段时间时,它会阻止 EDT 并阻止它执行需要执行的操作,包括显示加载窗口(顺便说一句,该窗口应该是一个对话框窗口,例如 JDialog 和不是应用程序窗口或 JFrame)。

解决方案:在后台线程(例如由 SwingWorker 提供的线程)中运行此方法调用。显示您的对话框窗口,并使用回调来通知您何时工作完成,从而何时不应再显示加载对话框窗口。

例如:

String search = filenameText.getText();
File root = new File(dirName);
resultText.setText("");

Loading show = new Loading();
show.setVisible(true);
displayDirectoryContents(root, search);
show.setVisible(false);

可以更改为类似的内容(注意代码未测试)

String search = filenameText.getText();
File root = new File(dirName);
resultText.setText("");

Loading show = new Loading();
show.setVisible(true);

// create our worker
new SwingWorker<Void, Void> worker = new SwingWorker<>(){
    @Override
    protected Void doInBackground() throws Exception {
        displayDirectoryContents(root, search);
        return null;
    }
};

worker.addPropertyChangeListener(evt -> {
    if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
        // you should also call get() on the worker allowing
        // you to capture and handle all exceptions it might throw
        show.setVisible(false);
    }
});

worker.execute();  // run the worker

更多请查看:Lesson: Concurrency in Swing

关于java - 创建 'loading...' 动画帧以在执行方法时显示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38103526/

相关文章:

java - 第 2 部分 - 如何在缩放 JTextPane 时获得一致的呈现?

java - 在 Java 中使用已发布的 MouseEvent 解决问题

php - 非阻塞 flock 函数的返回值与 $wouldblock 参数之间的区别?

java - 没有 happens-before 的安全发布?除了 final 还有什么?

java - 可见性和排序之间的关系/区别是什么?

java - 在生成的 list.jspx 中添加自定义列 url - Spring roo

java - 学习基本循环

java - Amazon Lambda 上 Amazon Echo/Alexa 的正确 Java handleRequest() 方法签名?

java - while(Matcher.find()) 无限循环

java - 单击 JButton 时尝试引用 JTextField 中的文本