Fork me on GitHub
#cljfx
<
2020-12-26
>
Seledrex14:12:02

Hello, I was wondering if anyone could help me with using fx/ext-many . I am trying to use this in order to show dialog windows above the main window.

3
Seledrex14:12:44

I currently am creating my app like this:

(def app
  (do
    (event-handler {:event/type ::events/initialize
                    :fx/sync true})
    (fx/create-app *state
                   :event-handler event-handler
                   :desc-fn views/desc)))
And my desc-fn is this:
(defn desc
  [{:keys [scene] :as state}]
  {:fx/type fx/ext-many
   :desc [{:fx/type root
           :state state}
          {:fx/type select-categories
           :state state}
          {:fx/type alert
           :state state}
          {:fx/type about
           :state state}]})
root , select-categories , alert , and about are all functions returning descriptions. I am getting this exception though, and I am not entirely sure what’s going wrong.

Seledrex14:12:44

java.lang.NullPointerException
	at clojure.core$deref_future.invokeStatic(core.clj:2300)
	at clojure.core$deref.invokeStatic(core.clj:2320)
	at clojure.core$deref.invoke(core.clj:2306)
	at cljfx.context$sub_ctx.invokeStatic(context.clj:107)
	at cljfx.context$sub_ctx.doInvoke(context.clj:106)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:669)
	at clojure.core$apply.invoke(core.clj:660)
	at cljfx.context$sub.invokeStatic(context.clj:165)
	at cljfx.context$sub.doInvoke(context.clj:161)
	at clojure.lang.RestFn.invoke(RestFn.java:442)
	at cljfx.lifecycle$sub_context_fn.invokeStatic(lifecycle.clj:473)
	at cljfx.lifecycle$sub_context_fn.invoke(lifecycle.clj:471)
	at cljfx.lifecycle$fn__1379.invokeStatic(lifecycle.clj:479)
	at cljfx.lifecycle$fn__1379.invoke(lifecycle.clj:478)
	at cljfx.lifecycle$eval1067$fn__1089$G__1054__1098.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__1139.create(lifecycle.clj:39)
	at cljfx.lifecycle$wrap_many$fn__1229$fn__1233$fn__1234.invoke(lifecycle.clj:280)
	at clojure.core$update.invokeStatic(core.clj:6196)
	at clojure.core$update.invoke(core.clj:6188)
	at cljfx.lifecycle$wrap_many$fn__1229$fn__1233.invoke(lifecycle.clj:279)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:343)
	at clojure.core$reduce.invokeStatic(core.clj:6827)
	at clojure.core$reduce.invoke(core.clj:6810)
	at cljfx.lifecycle$wrap_many$fn__1229.invoke(lifecycle.clj:278)
	at cljfx.lifecycle$eval1067$fn__1089$G__1054__1098.invoke(lifecycle.clj:17)
	at cljfx.lifecycle$wrap_map_desc$fn__1357.invoke(lifecycle.clj:446)
	at cljfx.lifecycle$eval1067$fn__1089$G__1054__1098.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__1139.create(lifecycle.clj:39)
	at cljfx.lifecycle$fn__1143.invokeStatic(lifecycle.clj:58)
	at cljfx.lifecycle$fn__1143.invoke(lifecycle.clj:56)
	at cljfx.lifecycle$eval1067$fn__1089$G__1054__1098.invoke(lifecycle.clj:17)
	at cljfx.lifecycle$wrap_map_desc$fn__1357.invoke(lifecycle.clj:446)
	at cljfx.lifecycle$eval1067$fn__1089$G__1054__1098.invoke(lifecycle.clj:17)
	at cljfx.lifecycle$wrap_context_desc$fn__1366.invoke(lifecycle.clj:458)
	at cljfx.lifecycle$eval1067$fn__1089$G__1054__1098.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__1691.invoke(renderer.clj:77)
	at cljfx.renderer$perform_render$fn__1642.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__1668$fn__1672.invoke(renderer.clj:44)
	at cljfx.renderer$request_render$fn__1668.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)

Seledrex14:12:25

I tried calling the root and other description functions directly inside the fx/ext-many description, but after an event would happen, the main window would be duplicated instead of updating the current main window.

Seledrex14:12:33

What am I doing wrong, or is there a better way to show dialogs windows?

Seledrex14:12:44

Previously, I was simply returning a different description each time, so only one window could only be on the screen at once, but I didn’t really like this approach. I wanted to be able to keep the main window open with the dialog popping up above.

Seledrex14:12:14

Doing this seemed to help:

(defn desc
  "Chooses which description to create"
  [{:keys [scene] :as state}]
  {:fx/type fx/ext-many
   :desc [(root state)
          (select-categories state)
          (alert state)
          (about state)]})
But still the main window gets duplicated once an event handler is fired and stuff is rendered again 👀

Seledrex14:12:00

It’s only getting duplicated once, and then on subsequent events, it’s not being duplicated

Seledrex16:12:08

Looks like I was able to resolve the problem myself. What I did above worked, but I had some application initialization errors that caused duplicate windows to be created. I fixed those and everything works now!

vlaaad07:12:58

Hey, sorry for late reply

vlaaad07:12:04

Glad you figured it out!