2016-12-21 3 views
1

Я пытаюсь заставить мое приложение отображать простой диалог загрузки, чтобы пользователи знали, когда работает интенсивный процесс и когда это делается. Я просто хочу, чтобы он показывал простую «загрузку» с помощью загруженного gif. Я уже пробовал использовать только текст, и он все еще не работает.Показать пользовательский диалог загрузки с gif

Я могу заставить диалоговое окно отображать (и исчезать), когда захочу, проблема в том, что ничего не будет отображаться в диалоговом окне (или кадре) после его отображения. Я пробовал много разных методов, и все они дают одинаковый результат, пустой диалог.

Наконец-то я создал отдельный класс для отображения диалогового окна (с загрузкой gif), и я получил его для отображения (сам по себе), но когда я запустил его из своего основного приложения, он снова отобразит черный диалог. Я тестировал установку gif в JOptionPane, и это работает, проблема в том, что я не могу закрыть его по своему усмотрению.

Вот мой код.

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(); 
      load.Close(); 
     } 
    } 

    private void createDialog(final Frame parent) { 

     dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
     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) { 
      String path = jfc.getSelectedFile().getAbsolutePath(); 
      String fileName = jfc.getSelectedFile().getName(); 

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

      load.Show(true); 
      createDoc(path); 
      load.Close(); 

     } 
    } 

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

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

Edit: Используйте этот файл для тестирования ->svg_test.svg

Я попытался назвать это так:

loader.show(true); 

, а также в своем собственном потоке, как это:

private void load(final Boolean visible) { 
    Thread t = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      loader.show(visible); 
     } 
    }); 

    t.start(); 
} 

Ни один из методов не работает и дает мне тот же результат, пустой диалог. У меня была эта проблема в прошлом, но я просто сдался и удалил ее (диалог загрузки). Я попробовал его с индикатором прогресса и простым текстом, ничего не работает.

Также я попробовал его на JOptionPane, и это сработало, но это нежелательно (я хочу закрыть/открыть, если не хочу, нажатием кнопки).

private void load() { 
     ImageIcon icon = new ImageIcon(MainForm.class.getResource("/resource/loader.gif").getFile()); 
     JOptionPane.showMessageDialog(null, "Loading...", "Loader", JOptionPane.INFORMATION_MESSAGE, icon); 
    } 

Я знаю, вы не можете запустить несколько диалогов на EDT и должны использовать отдельный поток, но я использую отдельный поток и он не работает (он работает сам по себе).

(Также обратите внимание, что у меня есть одно основное приложение (фрейм), которое запускает/открывает это второе диалоговое окно).

Любая помощь приветствуется.

+0

[mcve] или [sscce] (http://sscce.org) пожалуйста –

+0

К сожалению, забыл. Когда я закончу, я обновлю. –

+0

обновлен, откройте любой файл SVG, и он не будет работать. –

ответ

3

Вы хотите иметь проблему с потоками Swing, где у вас есть длинный код в потоке событий, испортивший рисование изображений, и я предполагаю, что длинный код работает в вашем методе createDoc. Подумайте о том, что это связано с фоновым потоком, например, с SwingWorker, и вызовом близко к вашему загрузочному объекту только после того, как работник завершил свою работу. Например, что-то вроде так:

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

     openFile(); 
     // load.Close(); // get rid of this 
    } 
} 

// ....... 

private void openFile() { 

    // .... 

    load.Show(true); // load dialog on event thread 

    new SwingWorker<Void, Void>() { 
     protected Void doInBackground() throws Exception { 
      createDoc(path); // call this from background thread 
      return null; 
     }; 

     protected void done() { 
      load.Close(); // only call this once createDoc has completed 
      // probably should call get() in here to catch all exceptions 
     }; 
    }.execute(); 
} 
+0

Вы были бы правы, строка, которая включает в себя «expression.evaluate», загружает документ SVG в объект (возможно, в память), который требует немного загрузки. В чем причина диалога загрузки. Я попробую это и посмотрю, работает ли оно. –

+0

Он работает! сладкое спасибо! –

+0

Другая проблема (второстепенная), как я могу использовать это с модальным диалогом? Мое текущее диалоговое окно немодально позволяет пользователям щелкнуть его и переместить. Я хочу, чтобы он ограничивал любые действия во время загрузки (чтобы предотвратить любые проблемы или проблемы). Я пытался настроить его модальным при создании, но он просто зависает и ничего не делает. Любой совет? –

Смежные вопросы