You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:53:09