我可以在没有JVM重启的情况下在JavaFX 8中重新加载样式表吗?

时间:2014-10-27 06:26:10

标签: java clojure javafx javafx-8

我正在使用Java 1.8u25,我正在使用如下的样式表(Java和Clojure等价物)。

//Java
new Pane().getStylesheets().add("some_style.css")

//Clojure
(doto (Pane.)
  (-> .getStylesheets (.add "some_style.css")))

我使用的是Clojure,我不会在测试运行之间重启JVM。但是,我会为每次运行创建一个新的GUI实例。 JavaFX在某处缓存样式表,因此编辑CSS文件无效。有没有办法强制JavaFX重新加载样式表?或者,重新加载类以便缓存丢失的方法?

2 个答案:

答案 0 :(得分:1)

请注意,您不是设置更改样式表,而是添加样式表:

new Pane().getStylesheets().add("some_style.css")

您调用add()方法!所以基本上它是你的Pane缓存先前加载的样式表。

解决方案很简单:在再次加载之前,删除(清除)旧的:

Pane p = new Pane();
// Load first time:
p.getStylesheets().add("some_style.css");

// Later to reload:
p.getStylesheets().clear();
p.getStylesheets().add("some_style.css");
    // some_style.css will be read again and applied

注意:

如果您使用多个CSS文件,clear()可能不是您想要的。在这种情况下,您可以使用clear()方法删除特定样式表(您要重新加载),而不是remove(),然后再重新添加。

注意#2:

加载CSS文件时,应使用URL到资源,而不仅仅是文件名。如果仅提供文件名,则它也必须包含包名。这样做既可以从文件系统也可以从jar文件中运行:

p.getStylesheets().add(YourClass.class.getResource("some_style.css")
    .toExternalForm()); // if some_style.css is next to YourClass.java

答案 1 :(得分:0)

我的开发方法是相同的:JavaFX在repl中使用Clojure,编辑CSS,而不重新启动JVM。

我发现以下两个“规则”适用:

  1. 不要将样式表添加到场景中。即使您尝试了本书中的所有技巧,它也不会更新(清晰)。奇怪的是,在关闭所有阶段之后的一定时间后,它的确发生了变化。虽然不知道为什么。 而是将其添加到父节点。
  2. 确保所有阶段均已关闭。如果打开了任何舞台,您的旧样式将不会更新。我认为与缓存和线程有关。

更新: 上面的代码不是很好,因为CSS不会应用于弹出窗口和对话框。 经过进一步的测试,我发现(也许是由于我在Clojure中构建JavaFX对象的方式,我需要在一定的延迟后将CSS重新“应用”到场景中。

我现在有以下代码片段,这些片段似乎对我来说很有效。
(我什至可以忽略“规则2”。)

(defn fxthread? []
  (Platform/isFxApplicationThread))

(defn later* [expr]
    (if (fxthread?)
      (try (expr) (catch Throwable e e (println e)))
      (Platform/runLater #(try (expr) (catch Throwable e e (println e))))))

(defmacro future-sleep-later [ms & body]
   `(future (Thread/sleep ~ms) (later* (fn [] ~@body))))

(defn external [path]
  (.toExternalForm (cio/resource (str path))))

(defn add-stylesheet [scene-or-parent path & [refresh? delay]]
  (let [css (external path)
        ss  (.getStylesheets scene-or-parent)]
    (.add ss css)
    (when refresh?
      (future-sleep-later (or delay 2000)
        (doto ss (.remove css) (.add css))))
    scene-or-parent))