0

在主程序加载大量数据期间,我在显示加载程序时遇到了问题。下面有一个名为SplashScreen的类,它显示加载器的 .gif 动画。

公共类 SplashScreen 扩展 JWindow {

public SplashScreen() {
    super();
    Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/resources/load.gif"));
    try {
        if (image != null) {
            JLabel imageLabel = new JLabel();
            imageLabel.setIcon(new ImageIcon(image));
            this.getContentPane().setLayout(new BorderLayout());
            this.getContentPane().add(imageLabel, BorderLayout.CENTER);
            this.pack();
            Dimension screenSize =
                    Toolkit.getDefaultToolkit().getScreenSize();
            Dimension labelSize = imageLabel.getPreferredSize();
            setLocation(screenSize.width / 2 - (labelSize.width / 2),
                    screenSize.height / 2 - (labelSize.height / 2));
            addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    dispose();
                }
            });
            addKeyListener(new KeyAdapter() {
                public void keyTyped(KeyEvent e) {
                    dispose();
                }
            });
        }
    } catch (Exception ex) {
    }
}

运行这段代码的结果是:

加载器 gif

但是当我想加载大量数据(比如 100 万条记录)时,我有这样的东西:

加载器 gif 空白

我使用 Thread、EventQueue.invokeLater 和 SwingUtilities 在单独的线程中显示 SplashScreen,但它不起作用。当我加载大量数据时,它总是空白。不幸的是,我必须说使用 EventQueue 或 SwingUtilities 非常困难,因为您无法结束由这些实用程序启动的任务。

4

1 回答 1

1

我终于想出了如何正确实施这种情况。

1) 实现 SplashScreen,它将显示加载程序 (.gif)

    public class SplashScreen extends JWindow {

        public SplashScreen() {
            super();
            Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/resources/load.gif"));
            try {
                if (image != null) {
                    JLabel imageLabel = new JLabel();
                    imageLabel.setIcon(new ImageIcon(image));
                    this.getContentPane().setLayout(new BorderLayout());
                    this.getContentPane().add(imageLabel, BorderLayout.CENTER);
                    this.pack();
                    Dimension screenSize =
                            Toolkit.getDefaultToolkit().getScreenSize();
                    Dimension labelSize = imageLabel.getPreferredSize();
                    setLocation(screenSize.width / 2 - (labelSize.width / 2),
                            screenSize.height / 2 - (labelSize.height / 2));
                    addMouseListener(new MouseAdapter() {
                        public void mouseClicked(MouseEvent e) {
                            dispose();
                        }
                    });
                    addKeyListener(new KeyAdapter() {
                        public void keyTyped(KeyEvent e) {
                            dispose();
                        }
                    });
                }
            } catch (Exception ex) {
            }
        }

        @Override
        public void dispose() {
            setVisible(false);
        }
}

2) 初始化ScheduledExecutorService

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

3)实现负责显示SplashScreen的Thread

Thread splashThread = new Thread(new Runnable() {
            public void run() {
                setSplashScreen(new SplashScreen());
                getSplashScreen().setVisible(true);
                getSplashScreen().toFront();
                getSplashScreen().setAlwaysOnTop(true);
            }
        });

4) 安排新创建的线程

executor.schedule(splashThread, 0, TimeUnit.MILLISECONDS);

5) 需要处理 SplashScreen 时

getSplashScreen().dispose();

此外,您可以创建单独的线程来检查是否需要处理 SplashScreen。

private void invokeExecutor() {
    executor.scheduleAtFixedRate(new DoneTask(), 0, 200, TimeUnit.MILLISECONDS);
}

private class DoneTask implements Runnable {
    @Override
    public void run() {
        if (fileWorker.isDone()) { //SwingWorker
            getSplashScreen().dispose();
        }
    }
}
于 2015-02-04T11:50:24.633 回答