2016-12-22 6 views
1

Wenn ich einen zweiten Dialog als 'Ladedialog' öffne, um Benutzeraktionen während des Ladens einer großen Datei zu verhindern, möchte ich, dass der Dialog alle Benutzeraktionen (Klicken und so weiter) einschränkt, während der Dialog geöffnet ist große Datei wird geladen). Der Dialog funktioniert als ein 'Nicht-Modaler Dialog', den Sie in das Hauptfenster zurückklicken können und auf den Sie klicken können. Wenn Sie stattdessen einen 'Modalen Dialog' verwenden, friert er die Prozesse des Programms ein, sobald diese angezeigt werden.Modaler Dialog funktioniert nicht

Wie kann ich den modalen Dialog richtig angezeigt bekommen?

Code:

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); 
     } 
    } 
} 

Antwort

3

Ich sehe, was du tust falsch, - Sie zeigen Aufruf, die Methode, die den modalen Dialog vor zeigt die Swingworker starten. Erneut erhalten Sie den SwingWorker und alle verkabelten und laufenden vor zeigt einen modalen Dialog.

Simplified Code (mit 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

Warum Sie den CreateDoc() Code entfernt hat? Das ist der Sinn des Codes und des Ladedialogs. Kann ich den Code ausführen, nachdem der Dialog angezeigt wird? –

+0

@lloyd lese den [mcve] -Link, da er erklärt, was ich getan habe. Zu Demonstrationszwecken kann dieser Code jeden lang laufenden Code mit Thread.sleep ersetzen. –

+0

Also würde ich meinen langen laufenden Code nur dort platzieren, wo der thread.sleep ist? –

Verwandte Themen