2016-12-22 65 views
1

當打開另一個對話框作爲「加載對話框」以阻止用戶在加載大文件時的操作時,我希望對話框限制任何用戶操作(單擊等),而對話框啓動時(以及大文件正在加載)。該對話框作爲一個「非模態對話框」,您可以單擊回主窗口並單擊東西,但是當使用「模態對話框」時,它會在程序顯示後凍結程序的進程。模式對話框不起作用

如何讓模態對話框正確顯示?

代碼:

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import javax.xml.parsers.*; 
import javax.xml.xpath.*; 
import java.util.logging.*; 
import org.w3c.dom.*; 
import java.io.File; 
import java.lang.reflect.InvocationTargetException; 
import java.net.URL; 
import javax.swing.filechooser.FileNameExtensionFilter; 

public class Loader implements Runnable { 

    final JFileChooser jfc = new JFileChooser(); 
    static JFrame frame = new JFrame(); 
    Frame parentUI = new Frame(); 
    JDialog dialog = new JDialog(); 
    JLabel lbl_filename = new JLabel(); 
    JLabel lbl_path = new JLabel(); 

    static Loader load = new Loader(null); 


    public static void main(String[] args) throws InterruptedException, InvocationTargetException { 
     load.run(); 
     frame.setVisible(true); 
    } 

    public Loader(Frame parent) { 
     init(); 
     parentUI = parent; 
    } 

    @Override 
    public void run() { 
     createDialog(parentUI); 
    } 

    public final void init() { 
     JButton btn = new JButton("Open"); 

     frame.setTitle("Loader Test"); 
     frame.setSize(500, 200); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocationRelativeTo(null); 
     frame.setLayout(new FlowLayout()); 

     btn.addActionListener(new Action1()); 

     frame.add(btn); 
     frame.add(lbl_filename); 
     frame.add(lbl_path); 
    } 

    class Action1 implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 

      openFile(); 
     } 
    } 

    private void createDialog(final Frame parent) { 

     dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
     dialog.setModal(true); 
     dialog.setTitle("Loader"); 

     URL url = this.getClass().getResource("/resource/loader.gif"); 
     Icon icon = new ImageIcon(url); 
     JLabel label = new JLabel(icon); 
     dialog.add(label); 

     dialog.pack(); 
     dialog.setLocationRelativeTo(parent); 
    } 


    public void Show(Boolean visible) { 
     this.run(); 
     dialog.setVisible(visible); 
    } 

    public void Close() { 
     dialog.setVisible(false); 
    } 

    private void setJFCFilter(String file, String ext) { 
     FileNameExtensionFilter filter = new FileNameExtensionFilter(file, ext); 
     jfc.setFileFilter(filter); 
    } 

    private void openFile() { 
     File default_dir = new File("."); 
     jfc.setCurrentDirectory(default_dir); 
     setJFCFilter("Scalable Vector Graphics", "svg"); 

     int returnVal = jfc.showOpenDialog(parentUI); 

     if (returnVal == JFileChooser.APPROVE_OPTION) { 
      final String path = jfc.getSelectedFile().getAbsolutePath(); 
      String fileName = jfc.getSelectedFile().getName(); 

      lbl_filename.setText(fileName); 
      lbl_path.setText(path); 

      System.out.println("Loading file..."); 

      load.Show(true); 

      new SwingWorker<Void, Void>() { 
       @Override 
       protected Void doInBackground() throws Exception { 
        createDoc(path); 
        return null; 
       }; 

       @Override 
       protected void done() { 
        load.Close(); 
       }; 
      }.execute(); 

      System.out.println("Closing file..."); 
     } 
    } 

    private void createDoc(String file) { 
     try { 
      NodeList svgIDPaths; 

      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
      DocumentBuilder builder = factory.newDocumentBuilder(); 
      Document doc = builder.parse(file); 

      String xpathIDExp = "//g/@id"; 

      XPathFactory xpf = XPathFactory.newInstance(); 
      XPath xpath = xpf.newXPath(); 
      XPathExpression expression = xpath.compile(xpathIDExp); 

      svgIDPaths = (NodeList)expression.evaluate(doc, XPathConstants.NODESET); // Java OutOfMemory 

     } catch (Exception ex) { 
      Logger.getLogger(Loader.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 
} 

回答

3

我看到你做錯了什麼, - 你調用顯示,顯示前的模態對話框開始SwingWorker的方法。再次,在之前顯示模式對話框,然後獲取SwingWorker和所有已連線並正在運行的

簡化代碼(帶了Thread.sleep)

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 

import java.util.concurrent.TimeUnit; 
import java.lang.reflect.InvocationTargetException; 
import java.net.URL; 

public class Loader implements Runnable { 
    static JFrame frame = new JFrame(); 
    Frame parentUI = new Frame(); 
    JDialog dialog = new JDialog(); 
    JLabel lbl_filename = new JLabel(); 
    JLabel lbl_path = new JLabel(); 

    static Loader load = new Loader(null); 

    public static void main(String[] args) throws InterruptedException, InvocationTargetException { 
     load.run(); 
     frame.setVisible(true); 
    } 

    public Loader(Frame parent) { 
     init(); 
     parentUI = parent; 
    } 

    @Override 
    public void run() { 
     createDialog(parentUI); 
    } 

    public final void init() { 
     JButton btn = new JButton("Open"); 

     frame.setTitle("Loader Test"); 
     frame.setSize(500, 200); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocationRelativeTo(null); 
     frame.setLayout(new FlowLayout()); 

     btn.addActionListener(new Action1()); 

     frame.add(btn); 
     frame.add(lbl_filename); 
     frame.add(lbl_path); 
    } 

    class Action1 implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      openFile(); 
     } 
    } 

    private void createDialog(final Frame parent) { 

     dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
     dialog.setModal(true); 
     dialog.setTitle("Loader"); 

     JLabel label = new JLabel("Label"); 
     dialog.add(label); 

     dialog.pack(); 
     dialog.setLocationRelativeTo(parent); 
    } 

    public void show(Boolean visible) { 
     this.run(); 
     dialog.setVisible(visible); 
    } 

    public void close() { 
     dialog.setVisible(false); 
    } 

    private void openFile() { 
     System.out.println("Loading file..."); 

     // !! load.show(true); 

     new SwingWorker<Void, Void>() { 
      @Override 
      protected Void doInBackground() throws Exception { 
       // createDoc(path); 
       createDoc(null); 
       return null; 
      }; 

      @Override 
      protected void done() { 
       load.close(); 
      }; 
     }.execute(); 

     load.show(true); //!! 
    } 

    private void createDoc(String file) { 
     try { 
      TimeUnit.SECONDS.sleep(4); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

你爲什麼要刪除createDoc()代碼?這就是代碼和加載對話框的全部要點。在顯示對話框後我能運行代碼嗎? –

+0

@lloyd讀取[mcve]鏈接,因爲它解釋了我所做的。出於演示目的,此代碼可以用Thread.sleep替換任何長時間運行的代碼。 –

+0

因此,我只是將我長期運行的代碼放在thread.sleep所在的位置? –