gpt4 book ai didi

qt - 如何将 Clojure REPL 与 Qt Jambi 一起使用?

转载 作者:太空宇宙 更新时间:2023-11-03 18:33:53 24 4
gpt4 key购买 nike

我还没有找到使用 Clojure 的解决方案REPL在网络上使用 Qt。基本上,问题是 REPL 在您调用 QApplication/exec 以显示 UI 时立即挂起。你不能 C-c C-c 回到 REPL,关闭事件的 Qt 窗口似乎会杀死整个 Clojure 进程。

现在不可能在代理中简单地调用 QApplication/processEvents,除非代理运行在与您创建 Qt 小部件完全相同的线程中。我花了两天时间才弄明白这个问题,我看到其他人也有同样的问题/问题,但没有解决方案。所以这是我的代码:

(add-classpath "file:///usr/share/java/qtjambi.jar")
(ns qt4-demo
(:import (com.trolltech.qt.gui QApplication QPushButton QFont QFont$Weight)
(com.trolltech.qt.core QCoreApplication)
(java.util Timer TimerTask)
(java.util.concurrent ScheduledThreadPoolExecutor TimeUnit))
(:require swank.core))

(defn init []
(QApplication/initialize (make-array String 0)))

(def *gui-thread* (new java.util.concurrent.ScheduledThreadPoolExecutor 1))
(def *gui-update-task* nil)
(def *app* (ref nil))

(defn update-gui []
(println "Updating GUI")
(QApplication/processEvents))

(defn exec []
(.remove *gui-thread* update-gui)
(def *gui-update-task* (.scheduleAtFixedRate *gui-thread* update-gui 0 150 (. TimeUnit MILLISECONDS))))

(defn stop []
(.remove *gui-thread* update-gui)
(.cancel *gui-update-task*))

(defmacro qt4 [& rest]
`(do
(try (init) (catch RuntimeException e# (println e#)))
~@rest
))

(defmacro with-gui-thread [& body]
`(.get (.schedule *gui-thread* (fn [] (do ~@body)) (long 0) (. TimeUnit MILLISECONDS))))

(defn hello-world []
(with-gui-thread
(qt4
(let [app (QCoreApplication/instance)
button (new QPushButton "Go Clojure Go")]
(dosync (ref-set *app* app))
(doto button
(.resize 250 100)
(.setFont (new QFont "Deja Vu Sans" 18 (.. QFont$Weight Bold value)))
(.setWindowTitle "Go Clojure Go")
(.show)))))
(exec))

基本上它使用 ScheduledThreadPoolExecutor 类来执行所有 Qt 代码。您可以使用 with-gui-thread 宏来更轻松地从线程内调用函数。这使得无需重新编译即可即时更改 Qt UI 成为可能。

最佳答案

如果您想使用 REPL 中的 Qt 小部件,QApplication/invokeLaterQApplication/invokeAndWait 可能是您想要的。您可以将它们与代理一起使用。鉴于此:

(ns qt4-demo
(:import (com.trolltech.qt.gui QApplication QPushButton)
(com.trolltech.qt.core QCoreApplication)))

(def *app* (ref nil))
(def *button* (ref nil))
(def *runner* (agent nil))

(defn init [] (QApplication/initialize (make-array String 0)))
(defn exec [] (QApplication/exec))

(defn hello-world [a]
(init)
(let [app (QCoreApplication/instance)
button (doto (QPushButton. "Go Clojure Go") (.show))]
(dosync (ref-set *app* app)
(ref-set *button* button)))
(exec))

然后来自 REPL:

qt4-demo=> (send-off *runner* hello-world)
#<Agent@38fff7: nil>

;; This fails because we are not in the Qt main thread
qt4-demo=> (.setText @*button* "foo")
QObject used from outside its own thread, object=QPushButton(0x8d0f55f0) , objectThread=Thread[pool-2-thread-1,5,main], currentThread=Thread[main,5,main] (NO_SOURCE_FILE:0)

;; This should work though
qt4-demo=> (QApplication/invokeLater #(.setText @*button* "foo"))
nil
qt4-demo=> (QApplication/invokeAndWait #(.setText @*button* "bar"))
nil

关于qt - 如何将 Clojure REPL 与 Qt Jambi 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1691453/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com