fx-clj
fx-clj copied to clipboard
Application crashes when I click on another window.
When I run the ubjerar, the application always crashes when I click on some other window (e.g. change tabs on a browser, or double click on the terminal). It doesn't crash in dev mode. Here is the sample core.clj I'm using:
(ns my-fx.core
(:gen-class)
(:require [fx-clj.core :as fx]))
(def app-state (atom {:output-to nil
:source-file nil}))
(defn create-grid []
(let [grid (fx/grid-pane {:alignment (javafx.geometry.Pos/CENTER)
:hgap 10
:vgap 10
:padding (javafx.geometry.Insets. 25 25 25 25)})
text-field (fx/text-field)
label (fx/label {:text "Your Message"})
btn (fx/button {:text "Say Hello"})
dir-label (fx/label {:text ""})
dir-btn (fx/button {:text "Choose directory"
:on-action (fn [e]
(let [dir-c (fx/pset! (javafx.stage.DirectoryChooser.))
output-dir (.showDialog dir-c (.getParent grid))]
(when output-dir
(swap! app-state assoc :output-to (.getAbsolutePath output-dir))
)))})
file-chosen-label (fx/label {:text ""})
file-choose-btn (fx/button {:text "Choose file"
:on-action (fn [e]
(let [file-chooser (fx/pset! (javafx.stage.FileChooser.))
file-chosen (.showOpenDialog file-chooser (.getParent grid))]
(when file-chosen
(swap! app-state assoc :source-file file-chosen))))})]
;; Watch for changes to the application state.
(add-watch app-state
:app-state
(fn [k a old-state new-state]
;;Display the directory chosen where we want to save our file.
(when (:output-to new-state)
(fx/pset! dir-label {:text (:output-to new-state)}))
;;Display the file we selected
(when (:source-file new-state)
(fx/pset! file-chosen-label {:text (.getCanonicalPath (:source-file new-state))}))))
(.add grid label 0 1)
(.add grid text-field 1 1)
(.add grid dir-btn 0 2)
(.add grid dir-label 1 2)
(.add grid file-choose-btn 0 3)
(.add grid file-chosen-label 1 3)
(.add grid btn 1 5 2 2)
grid))
(defn -main [& args]
(fx/sandbox #'create-grid :title "My Fx"))
(comment
(reset! app-state {:output-to nil
:source-file nil})
(fx/sandbox #'create-grid :title "My Fx")
)
So the sandbox is really only for use in development mode for fast iterations (it has refresh support - activated by hitting F5). When you're building an uberjar, you want to launch your view with some other method.
FWIW, here's a simplified version of what my app uses:
(ns my-app.main
(:gen-class)
(:require
[my-app.core :refer [my-app-view]]
[fx-clj.core :as fx])
(:import (javafx.stage Modality)
(java.awt SplashScreen)))
(defn start-app
[app-fn & {:keys [title maximized]}]
(fx/run<!!
(let [scene (fx/scene (app-fn))
stage (fx/stage)]
(.setScene stage scene)
(.initModality stage Modality/NONE)
(fx/pset! stage {:title title})
(when maximized (.setMaximized stage true))
(.show stage)
(let [splash-screen (SplashScreen/getSplashScreen)]
(when splash-screen
(try
(.close splash-screen)
(catch Exception ex))))
stage)))
(defn -main [& args]
(start-app my-app-view
:title "MyApp"
:maximized true))
I get the same behavior with that. I created a repo that shows this in action: https://github.com/uris77/my-fx
I've increased the time the application stays up by re-writing run.clj but leaving out the require of bootstrap.clj. I noticed it is also pulled in by other namespaces. Is there any way to not pull it in?
Nevermind my previous comment about disabling bootstrap globally. I realized that is a bad idea.