使用cl-gtk4无法热重载:主函数阻塞问题求助
解决方案
核心原因是默认调用(test-app)会启动GTK的主循环并阻塞当前线程(即REPL所在线程),导致后续代码无法被求值。要实现热重载,必须让GTK主循环在后台线程运行,保留REPL的交互能力。
方法一:用线程启动主循环
先加载跨平台线程库bordeaux-threads,再将主函数放到后台线程执行:
(ql:quickload '(:cl-gtk4 :bordeaux-threads)) (gtk4:define-application (:name test-app :id "org.testorg.testapp") (gtk4:define-main-window (window (gtk4:make-application-window :application gtk4:*application* )) (setf (gtk4:window-title window) "Test App" (gtk4:window-default-size window) '(800 600)) (gtk4:window-present window))) ;; 后台启动GTK主循环,不阻塞REPL (bordeaux-threads:make-thread #'test-app :name "GTK Main Loop")
方法二:禁用自动主循环,手动后台启动
利用define-application的:run-main-loop参数,避免自动阻塞,再手动将主循环放到后台:
(ql:quickload '(:cl-gtk4 :bordeaux-threads)) (gtk4:define-application (:name test-app :id "org.testorg.testapp" :run-main-loop nil) (gtk4:define-main-window (window (gtk4:make-application-window :application gtk4:*application* )) (setf (gtk4:window-title window) "Test App" (gtk4:window-default-size window) '(800 600)) (gtk4:window-present window))) ;; 启动应用后,后台运行GTK主循环 (test-app) (bordeaux-threads:make-thread (lambda () (gtk4:main)) :name "GTK Main Loop")
热重载的正确操作
- 用上述任一方式启动应用,确保REPL保持可交互状态
- 修改代码后,用Slimv的
,d重新定义窗口逻辑 - 直接修改已存在的窗口对象属性:
- 先将窗口变量设为全局可访问,比如在定义中加入
(defvar *main-window* nil),并在窗口初始化时赋值(setf *main-window* window) - 修改标题时直接在REPL执行:
(setf (gtk4:window-title *main-window*) "Updated Title") - 如果需要重建窗口,可先销毁旧窗口
(gtk4:window-destroy *main-window*),再重新执行窗口定义代码
- 先将窗口变量设为全局可访问,比如在定义中加入
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

