在一个名为 gui.clj
的源文件中,我定义了一个框架 fr
,用于保存应用程序的窗口,如下所示:
(def fr (frame ...))
还有一个run
函数,用于设置fr
并在数据更改时使其重新绘制,如下所示(以scribble.clj为模型:
(defn run []
(-> fr add-behaviors pack! show!)
(when-data-changes
(swap! state assoc :shapes (dot/g->seesaw t/ws))
(repaint! fr)))
当我在 REPL 中乱搞时,我经常修改源文件,然后调用 c.t.n.repl/refresh
.当我再次运行run
时,它会打开一个新窗口,将旧窗口留在屏幕上。如何在刷新后使我的(新更新的)代码在同一窗口上运行?
可以将应用程序的状态(包含窗口对象)放入单独命名空间中的defonce
中,并在命名空间上调用 disable-reload。这将防止在调用 (refresh)
时重新加载命名空间,从而保持原始状态(包含原始窗口对象)。
但是,在实践中,通常最好在重新加载时清理并重新启动应用程序。保留某些命名空间先前状态中的过时对象可能很危险。使用组件或装载来管理应用程序状态。
听起来您希望为程序的有状态部分提供一点"生命周期",有点像
- 如果不存在,则使其存在
- 让它运行
- 清理它
并希望在您重新加载时发生这种情况。您可以通过向清除窗口的清理函数添加代码来使同一窗口继续存在并获取新内容,也可以关闭窗口并为每个周期创建一个新窗口。
我已经将组件库用于使用这种风格的大型项目,它非常有效,尽管习惯它有点生活方式的改变。对于您的情况,您可能只想初始化一个存储活动窗口的 Atom,然后定义对该 Atom 的内容进行操作的三个基本生命周期函数。(并将实际原子放在defonce
中)