This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-01-05
Channels
- # announcements (14)
- # babashka (51)
- # beginners (154)
- # calva (24)
- # cider (4)
- # clj-kondo (24)
- # cljfx (11)
- # cljs-dev (3)
- # clojure (259)
- # clojure-europe (14)
- # clojure-nl (2)
- # clojure-seattle (8)
- # clojure-spec (6)
- # clojure-taiwan (1)
- # clojure-uk (52)
- # clojurescript (123)
- # conjure (43)
- # core-async (15)
- # datomic (14)
- # events (1)
- # fulcro (90)
- # helix (7)
- # jobs (6)
- # meander (10)
- # nrepl (1)
- # off-topic (13)
- # pathom (1)
- # portal (8)
- # re-frame (7)
- # reveal (11)
- # shadow-cljs (99)
- # spacemacs (11)
- # testing (11)
- # vim (63)
I’m trying to figure out a good workflow to develop a UI with cljfx
in IntelliJ IDEA with the CrusiveIDE plugin… is there a way to update/reload the UI when the corresponding source file is saved or when a component gets compiled? I understand that I can call (renderer)
to “reload” the UI after changing the code but it would be nice if that could happen automatically.
I also use (swap! *state identity)
to touch state atoms, that triggers a normal update (e.g. not a full re-create)
I do something like this:
(defonce *state
(atom {:app-title "Proto App"}))
(defn root [{:keys [app-title]}]
{:fx/type :stage
:showing true
:title app-title
;...
})
(defonce renderer
(fx/create-renderer
:middleware (fx/wrap-map-desc assoc :fx/type root)))
(fx/on-fx-thread
(fx/mount-renderer *state renderer))
And updating *state
with (swap! *state assoc-in [:app-title] "Foo")
changes the title. But when changing and compiling root
those changes will not take effect on the next (swap! *state …)
. While tying, I think I know what’s wrong…When defining the renderer like this:
(def renderer
(fx/create-renderer
:middleware (fx/wrap-map-desc assoc :fx/type #'root)))
I get:
java.lang.IllegalArgumentException: No implementation of method: :create of protocol: #'cljfx.lifecycle/Lifecycle found for class: clojure.lang.Var
at clojure.core$_cache_protocol_fn.invokeStatic(core_deftype.clj:583)
at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:575)
at cljfx.lifecycle$eval2423$fn__2445$G__2410__2454.invoke(lifecycle.clj:17)
at cljfx.lifecycle$create_dynamic_component.invokeStatic(lifecycle.clj:32)
at cljfx.lifecycle$create_dynamic_component.invoke(lifecycle.clj:29)
at cljfx.lifecycle$reify__2495.create(lifecycle.clj:39)
at cljfx.lifecycle$fn__2499.invokeStatic(lifecycle.clj:58)
at cljfx.lifecycle$fn__2499.invoke(lifecycle.clj:56)
at cljfx.lifecycle$eval2423$fn__2445$G__2410__2454.invoke(lifecycle.clj:17)
at cljfx.lifecycle$wrap_map_desc$fn__2713.invoke(lifecycle.clj:446)
at cljfx.lifecycle$eval2423$fn__2445$G__2410__2454.invoke(lifecycle.clj:17)
at cljfx.renderer$render_component.invokeStatic(renderer.clj:57)
at cljfx.renderer$render_component.invoke(renderer.clj:47)
at cljfx.renderer$create$fn__3047.invoke(renderer.clj:77)
at cljfx.renderer$perform_render$fn__2998.invoke(renderer.clj:23)
at cljfx.renderer$perform_render.invokeStatic(renderer.clj:22)
at cljfx.renderer$perform_render.invoke(renderer.clj:14)
at cljfx.renderer$request_render$fn__3024$fn__3028.invoke(renderer.clj:44)
at cljfx.renderer$request_render$fn__3024.invoke(renderer.clj:44)
at clojure.lang.AFn.run(AFn.java:22)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
ah, no, cljfx doesn’t accept vars as fx/type by default, I meant (fx/wrap-map-desc #'root)
which calls map fn outside of cljfx lifecycle. The thing is, you need to have clojure code that has var dereferencing at call site for var reloading to work, and (fx/wrap-map-desc assoc :fx/type root)
does dereferencing only on call to fx/wrap-map-desc