簡體   English   中英

顯示帶有gif的自定義加載對話框

[英]Show custom loading dialog with 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);
        }
    }
}  

編輯:使用此文件進行測試-> 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上運行多個對話框,而必須使用單獨的線程,但是我使用的是單獨的線程,並且該線程不起作用(它可以單獨工作)。

(還要注意,我有一個正在運行/打開第二個對話框的主應用程序(框架))。

任何幫助表示贊賞。

您似乎遇到了Swing線程問題,在事件線程上有長時間運行的代碼弄亂了圖像的繪制,我想這是長時間運行的代碼在createDoc方法中。 考慮從諸如SwingWorker之類的后台線程調用該函數,並僅在worker完成其工作之后才對load對象調用close。 例如這樣的事情:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM