Non ho trovato una soluzione per utilizzare ClojureREPL con Qt sul web. Fondamentalmente il problema è che il REPL si blocca non appena si chiama QApplication/exec per visualizzare l'interfaccia utente. Non puoi C-c C-c tornare in REPL, e chiudere la finestra Qt attiva sembra uccidere l'intero processo Clojure.Come posso utilizzare il REPL Clojure insieme a Qt Jambi?
Ora la semplice chiamata di QApplication/processEvents dall'interno di un agente non è possibile, a meno che l'agente non funzioni esattamente nello stesso thread in cui sono stati creati i widget Qt. Mi ci sono voluti due giorni per capirlo e ho visto che gli altri hanno lo stesso problema/problema ma senza una soluzione. Così qui è il mio, in codice:
(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#)))
[email protected]
))
(defmacro with-gui-thread [& body]
`(.get (.schedule *gui-thread* (fn [] (do [email protected])) (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))
Fondamentalmente si utilizza la classe ScheduledThreadPoolExecutor al fine di eseguire tutte le Qt-code. È possibile utilizzare la macro con gui-thread per rendere più semplice la chiamata di funzioni all'interno del thread. Ciò rende possibile cambiare l'interfaccia utente Qt al volo, senza ricompilare.
Sì, ho dovuto fare la stessa cosa. – levand
Non so nulla di QT. Ma perché vuoi farlo? Clojure ha accesso a Swing, una struttura GUI molto potente e versatile. Ti stai connettendo a una GUI QT già installata? –
QT è decisamente migliore di Swing in molti modi, comprese le prestazioni e il look and feel nativo. – levand