如何在Cljfx中从菜单项访问主窗口(:stage)
在Cljfx中从菜单点击事件访问主窗口(Stage)
要实现菜单点击后操作主窗口(打开文件选择器、调整窗口大小),可以通过以下两种方法获取Stage实例:
方法1:将Stage存入状态(推荐,契合Cljfx状态管理思路)
Cljfx开发通常会配合状态原子(atom)管理应用状态,我们可以在创建Stage时把实例保存到状态中,后续菜单事件直接从状态里取即可。
(ns a (:require [cljfx.api :as fx] [javafx.stage.FileChooser :as fc])) ; 用原子存储主窗口Stage实例 (def app-state (atom {})) (defn handle-menu-click [] (let [stage (:main-stage @app-state)] ; 1. 打开文件选择器 (let [file-chooser (fc.)] (.showOpenDialog file-chooser stage)) ; 2. 调整窗口大小为800x600 (.setWidth stage 800) (.setHeight stage 600))) (fx/on-fx-thread (let [stage (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 (fn [_] (handle-menu-click))}]}]}]}})] ; 将创建好的Stage存入状态 (swap! app-state assoc :main-stage stage)))
方法2:从事件源向上遍历获取Stage(无需状态存储)
如果不想引入状态管理,可以利用JavaFX的组件层级关系,从菜单点击事件的源组件出发,逐层向上找到对应的Stage:
(ns a (:require [cljfx.api :as fx] [javafx.stage.FileChooser :as fc])) (defn handle-menu-click [event] (let [; 从事件源获取MenuItem,再向上找到Scene和Stage menu-item (.getSource event) scene (.getScene menu-item) stage (.getWindow scene)] ; 1. 打开文件选择器 (let [file-chooser (fc.)] (.showOpenDialog file-chooser stage)) ; 2. 调整窗口大小 (.setWidth stage 800) (.setHeight stage 600))) (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 handle-menu-click}]}]}]}}}))
两种方法对比
- 方法1适合中大型应用,符合Cljfx的状态驱动开发模式,便于统一管理窗口实例;
- 方法2适合小型演示或快速原型,无需额外维护状态,直接通过组件层级获取Stage。
内容的提问来源于stack exchange,提问作者kamwitsta
相关产品推荐
相关产品推荐

