javafxclojureclojure-java-interopcljfx

Accessing the window from a menu item in Cljfx


How can I access the main window (:stage) from a menu click event in Cljfx? I need it for two reasons: to open a file chooser, and to resize the window.

A minimal example:

(ns a
  (:require [cljfx.api :as fx]))

(fx/on-fx-thread
  (fx/create-component
    {:fx/type :stage
     :showing true
     :scene {:fx/type :scene
             :root {:fx/type :v-box
                    :children [{:fx/type :menu-bar
                                :menus [{:fx/type :menu
                                         :text "Test"
                                         :items [{:fx/type :menu-item
                                                  :text "test"
                                                  :on-action #(println %)}]}]}]}}}))

; deps.edn
; {:deps  {org.clojure/clojure {:mvn/version "1.12.0"}
;          cljfx/cljfx         {:mvn/version "1.9.5"}}}


Solution

  • In your ns form (not necessary, but needed to fix reflection warnings if you have (set! *warn-on-reflection* true) in that namespace):

    (:import (javafx.event Event)
             (javafx.scene.control MenuItem)
             (javafx.stage PopupWindow))
    

    As a handler for :on-action:

    (fn [^Event evt]
      (let [^MenuItem menu-item (.getTarget evt)
            ^PopupWindow menu (.getParentPopup menu-item)
            stage (.getOwnerWindow menu)]
        ...))