2

我正在设计一个简单的 JavaFX 表单。

首先,我加载 JavaFX 环境(并等待它完成),如下所示:

final CountDownLatch latch_l = new CountDownLatch(1);
try {
    // init the JavaFX environment
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new JFXPanel(); // init JavaFX
            latch_l.countDown();
        }
    });
    latch_l.await();
}

这工作正常。(之所以需要先用这种方式加载JavaFX,是因为它主要是一个Swing应用,里面有一些JavaFX组件,不过是后面加载的)

现在,我想在启动时添加一个启动画面,并在 JavaFX 环境加载时显示它(实际上在屏幕上显示了大约 5 秒,因为我的应用程序有徽标、商标等)需要出示)

所以我想出了一个 SplashScreen 类,它只在屏幕上显示一个 JWindow,就像这样:

public class SplashScreen {

    protected JWindow splashScreen_m = new JWindow();
    protected Integer splashScreenDuration_m = 5000;

    public void show() {
        // fill the splash-screen with informations
        ...

        // display the splash-screen
        splashScreen_m.validate();
        splashScreen_m.pack();
        splashScreen_m.setLocationRelativeTo(null);
        splashScreen_m.setVisible(true);
    }

    public void unload() {
        // unload the splash-screen
        splashScreen_m.setVisible(false);
        splashScreen_m.dispose();
    }
}

现在,我希望启动画面加载并显示自身 5 秒。同时,我也希望加载 JavaFX 环境。

所以我像这样更新了 CountDownLatch :

final CountDownLatch latch_l = new CountDownLatch(2); // now countdown is set to 2

final SplashScreen splash_l = new SplashScreen();

try {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            // show splash-screen
            splash_l.show();
            latch_l.countDown();

            // init the JavaFX environment
            new JFXPanel(); // init JavaFX
            latch_l.countDown();
        }
    });
    latch_l.await();
    splash_l.unload();
}

所以,它正在工作,但飞溅只停留在 JavaFX 环境加载,所以基本上它卸载得非常快(这是正常的,考虑到我编写的代码)。

如何在不冻结 EDT 的情况下至少显示 5 秒的闪屏(如果 JavaFX 加载速度更快)?

谢谢。

4

1 回答 1

4

最重要的问题是您阻塞了事件调度线程,这意味着它在被阻塞时无法显示/更新任何内容。同样的问题也适用于 JavaFX。

你也应该永远不要从它们各自的事件队列之外的任何东西中更新。

现在,有很多方法可以解决这个问题,但SwingWorker可能是目前最简单的方法。

在此处输入图像描述

我道歉,这是我对 JavaFX 的全部曝光......

public class TestJavaFXLoader extends JApplet {

    public static void main(String[] args) {
        new TestJavaFXLoader();
    }

    public TestJavaFXLoader() throws HeadlessException {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                Loader loader = new Loader();
                loader.addPropertyChangeListener(new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        if (evt.getPropertyName().equals("state") && evt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
                            System.out.println("Load main app here :D");
                        }
                    }
                });
                loader.load();
            }
        });
    }

    public class Loader extends SwingWorker<Object, String> {

        private JWindow splash;
        private JLabel subMessage;

        public Loader() {
        }

        protected void loadSplashScreen() {
            try {
                splash = new JWindow();
                JLabel content = new JLabel(new ImageIcon(ImageIO.read(...))));
                content.setLayout(new GridBagLayout());
                splash.setContentPane(content);

                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;

                subMessage = createLabel("");

                splash.add(createLabel("Loading, please wait"), gbc);
                splash.add(subMessage, gbc);
                splash.pack();
                splash.setLocationRelativeTo(null);
                splash.setVisible(true);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        protected JLabel createLabel(String msg) {
            JLabel message = new JLabel("Loading, please wait");
            message.setForeground(Color.CYAN);
            Font font = message.getFont();
            message.setFont(font.deriveFont(Font.BOLD, 24));
            return message;
        }

        public void load() {
            if (!EventQueue.isDispatchThread()) {
                try {
                    SwingUtilities.invokeAndWait(new Runnable() {
                        @Override
                        public void run() {
                            loadSplashScreen();
                        }
                    });
                } catch (Exception exp) {
                    exp.printStackTrace();
                }
            } else {
                loadSplashScreen();
            }
            execute();
        }

        @Override
        protected void done() {
            splash.dispose();
        }

        @Override
        protected void process(List<String> chunks) {
            subMessage.setText(chunks.get(chunks.size() - 1));
        }

        @Override
        protected Object doInBackground() throws Exception {

            publish("Preparing to load application");
            try {
                Thread.sleep(2500);
            } catch (InterruptedException interruptedException) {
            }
            publish("Loading JavaFX...");

            runAndWait(new Runnable() {
                @Override
                public void run() {
                    new JFXPanel();
                }
            });

            try {
                Thread.sleep(2500);
            } catch (InterruptedException interruptedException) {
            }
            return null;
        }

        public void runAndWait(final Runnable run)
                throws InterruptedException, ExecutionException {
            if (Platform.isFxApplicationThread()) {
                try {
                    run.run();
                } catch (Exception e) {
                    throw new ExecutionException(e);
                }
            } else {
                final Lock lock = new ReentrantLock();
                final Condition condition = lock.newCondition();
                lock.lock();
                try {
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            lock.lock();
                            try {
                                run.run();
                            } catch (Throwable e) {
                                e.printStackTrace();
                            } finally {
                                try {
                                    condition.signal();
                                } finally {
                                    lock.unlock();
                                }
                            }
                        }
                    });
                    condition.await();
//                    if (throwableWrapper.t != null) {
//                        throw new ExecutionException(throwableWrapper.t);
//                    }
                } finally {
                    lock.unlock();
                }
            }
        }
    }
}

我在这里runAndWait找到了代码

于 2013-02-18T03:20:54.077 回答