fx-clj icon indicating copy to clipboard operation
fx-clj copied to clipboard

Application crashes when I click on another window.

Open uris77 opened this issue 10 years ago • 4 comments

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")
)

uris77 avatar Nov 10 '15 23:11 uris77

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))

aaronc avatar Nov 10 '15 23:11 aaronc

I get the same behavior with that. I created a repo that shows this in action: https://github.com/uris77/my-fx

uris77 avatar Nov 11 '15 01:11 uris77

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?

uris77 avatar Nov 11 '15 02:11 uris77

Nevermind my previous comment about disabling bootstrap globally. I realized that is a bad idea.

uris77 avatar Nov 11 '15 03:11 uris77