2017-04-21 65 views
0

在Netbeans中,我创建了一个GUI项目,该项目使用框架前端,我可以添加组件并双击编辑它们的事件。我指的是具有“源”,“设计”和“历史”选项卡的窗口。未显示java SwingWorker对话框

下面是组件和关系:

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

2-一个TextArea来显示文件选择器的结果。如果用户选择一个文件,它将在TextArea中显示文件名;否则会写入“被用户取消”。与此同时,如果用户选择了一个文件,我想打开一个“请稍候”对话框,女巫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:我用的SwingWorker代码解释here

回答

1

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

相反,利用SwingWorker小号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.sleep暂停doInBackground方法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); 
    } 

} 
+0

我怀疑后台任务正在运行,因为没有操作循环(延迟)不会执行。请解释更多。 – mahmood

+0

你怎么知道,你不会在'doInBackground'方法中打印任何东西。 我毫不怀疑它的工作,除非if(result!= JFileChooser.APPROVE_OPTION){'是'true',它必须运行。我也毫不怀疑'get'是一种阻止方法,它是文档。尝试更新的示例。如果它仍然不起作用,那么您需要提供一个可运行的示例来说明您的问题。另一个问题是工作人员完成的速度如此之快,以至于窗口在屏幕上可以实现之前就已经关闭了。 – MadProgrammer

+0

哪个导入行与'addPropertyChangeListener'有关? – mahmood