我正在使用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重新加载样式表?或者,重新加载类以便缓存丢失的方法?
请注意,您没有设置或更改样式表,而是添加样式表:
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
我的开发方法是一样的:JavaFX在repl中使用Clojure,编辑css,而不是重启JVM。
我发现以下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))