【问题标题】:java SwingWorker dialog is not shown未显示 java SwingWorker 对话框
【发布时间】:2017-09-18 02:48:44
【问题描述】:

在 Netbeans 中,我创建了一个 GUI 项目,它使用框架前端,我可以添加组件并双击以编辑它们的事件。我指的是具有“来源”、“设计”和“历史”标签的窗口。

以下是组件和关系:

1- 打开文件选择器的按钮。

2- 显示文件选择器结果的 TextArea。如果用户选择一个文件,它将在 TextArea 中显示文件名;否则会写“被用户取消”。

3- 同时,如果用户选择了一个文件,我想打开一个“请稍候”对话框,女巫SwingWorker 并在后台做一些工作。

问题是,当用户选择一个文件时,我没有看到请稍候对话框!! Netbeans 生成的完整代码可在pastebin 获得。部分代码如下所示:

private void OpenSongFileActionPerformed(java.awt.event.ActionEvent evt) {                                              
    // TODO add your handling code here:
    JFileChooser fileChooser = new JFileChooser();
    fileChooser.setAcceptAllFileFilterUsed(false);
    FileNameExtensionFilter filter = new FileNameExtensionFilter("MP3 files", "mp3");
    fileChooser.addChoosableFileFilter(filter);
    fileChooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
    int result = fileChooser.showOpenDialog(this);
    if (result != JFileChooser.APPROVE_OPTION) {
        //ReadInfo.setText("No song has been selected");
        System.out.println("OpenSongFile canceled by user");
        return;
    }
    final JDialog loading = new JDialog(this);
    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(this);
    loading.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
    loading.setModal(true);
    SwingWorker<String, Void> worker = new SwingWorker<String, Void>() {
        @Override
        protected String doInBackground() throws InterruptedException {
            for (int i = 0; i < 10000; i++) 
                for (int j = 0; j < 10000; j++) 
                    ;
            return "hello";
        }
        @Override
        protected void done() {
            loading.dispose();
        }
    };
    worker.execute();
    loading.setVisible(true);
    try {
        worker.get();
    } catch (Exception e1) {
        e1.printStackTrace();
    }

    File selectedFile = fileChooser.getSelectedFile();
    ReadInfo.setText("Selected file: " + selectedFile.getAbsolutePath());
}                              

P.S:我使用了 here 解释的 SwingWorker 代码。

【问题讨论】:

    标签: java swing jframe swingworker


    【解决方案1】:

    worker.get(); 将一直阻塞,直到 SwingWorker 返回,这意味着您正在阻塞 EDT,从而阻止显示对话框。

    相反,请使用SwingWorkers PropertyChangeListener 支持并监控STARTDONE 事件

    SwingWorker<String, Void> worker = new SwingWorker<String, Void>() {
        @Override
        protected String doInBackground() throws InterruptedException {
            Thread.sleep(5000);
            return "hello";
        }
    
        @Override
        protected void done() {
            loading.dispose();
        }
    };
    worker.addPropertyChangeListener(new PropertyChangeListener() {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            System.out.println(evt.getPropertyName());
            Object value = evt.getNewValue();
            if (value instanceof SwingWorker.StateValue) {
                SwingWorker.StateValue state = (SwingWorker.StateValue) value;
                switch (state) {
                    case DONE: {
                        try {
                            String result = worker.get();
                            JOptionPane.showMessageDialog(null, result);
                        } catch (InterruptedException | ExecutionException ex) {
                            ex.printStackTrace();
                        }
                    }
                    break;
                }
            }
        }
    });
    worker.execute();
    loading.setVisible(true);
    

    另一个问题是你的循环可能运行得太快了,以至于窗口在它出现在屏幕上之前就被关闭了。

    例如,我只是简单地使用Thread.sleepdoInBackground 方法暂停5 秒...

    import java.awt.BorderLayout;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.util.concurrent.ExecutionException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.swing.JDialog;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.SwingWorker;
    
    public class Memory extends JFrame {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    makeItSo();
                }
            });
        }
    
        public static void makeItSo() {
            final JDialog loading = new JDialog();
            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(null);
            loading.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
            loading.setModal(true);
            SwingWorker<String, Void> worker = new SwingWorker<String, Void>() {
                @Override
                protected String doInBackground() throws InterruptedException {
                    Thread.sleep(5000);
                    return "hello";
                }
    
                @Override
                protected void done() {
                    loading.dispose();
                }
            };
            worker.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    System.out.println(evt.getPropertyName());
                    Object value = evt.getNewValue();
                    if (value instanceof SwingWorker.StateValue) {
                        SwingWorker.StateValue state = (SwingWorker.StateValue) value;
                        switch (state) {
                            case DONE: {
                                try {
                                    String result = worker.get();
                                    JOptionPane.showMessageDialog(null, result);
                                } catch (InterruptedException | ExecutionException ex) {
                                    ex.printStackTrace();
                                }
                            }
                            break;
                        }
                    }
                }
            });
            worker.execute();
            loading.setVisible(true);
        }
    
    }
    

    【讨论】:

    • 我怀疑后台任务是否正在运行,因为没有执行无操作循环(延迟)。请解释更多。
    • 你怎么知道,doInBackground 方法中没有打印任何内容。我毫不怀疑它正在工作,除非if (result != JFileChooser.APPROVE_OPTION) {true,否则它必须运行。我也毫不怀疑get 是一种阻塞方法,它就是这样的文档。尝试更新的示例。如果它仍然不起作用,那么您需要提供一个可运行的示例来演示您的问题。另一个问题是工人完成得太快以至于窗口在屏幕上实现之前就关闭了
    • 哪些导入行与addPropertyChangeListener相关?
    • import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;
    • 嗯,我发布的第二个示例基于您的代码,就是这样做的。它显示在您的另一个框架的“顶部”。您使用框架glassPane to produce a "blocked" view 或类似this instead
    猜你喜欢
    • 2013-06-28
    • 2016-05-30
    • 2017-02-05
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多