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 秒間画面に表示されます。示す必要があります)

そこで、次のように JWindow を画面に表示するだけの SplashScreen クラスを思いつきました。

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 に答える