I have a listbox that needs to be updated periodically by a separate thread. However, I am having trouble figuring out how to make that happen. This code fails with a stream error, probably because the wish stream is not accessible to the spawned thread:
(ltk:with-ltk (:debug 3) (let* ((update-threads nil) (f (make-instance 'ltk:frame)) (m1 (ltk:make-menubar)) (mf (ltk:make-menu m1 "File")) (call-queue-listbox (make-instance 'ltk:listbox :name "call_q" :master f :width 30 :height 12)) (exit-fn #'(lambda () (setq *shutdown-gui* t) (dolist (thread update-threads) (join-thread thread)) (setq update-threads nil) (setf ltk:*exit-mainloop* t))) (mf-exit (ltk:make-menubutton mf "Quit" exit-fn))) (ltk:pack f) (ltk:grid call-queue-listbox 0 0) (ltk:bind ltk:*tk* "<Alt-q>" (lambda (event) (declare (ignore event)) (funcall exit-fn))) (push (make-thread #'(lambda () (loop until *shutdown-gui* do (ltk:listbox-clear call-queue-listbox) (dotimes (i (random 10)) (ltk:listbox-append call-queue-listbox (format nil "call ~A in queue" i))) (sleep 1)))) update-threads)))
Can someone show me the correct ltk idiom for this?
Thanks!
-Kevin
Hi Kevin,
in general LTk has no support for multithreading. Mostly because threads are supported only by a few common lisp implementations and that updating a user-interface requires some synchronisation of some sort. Which Lisp implementation are you using? In the presence of multi-threading, I would strongly suggest to only communicate with Tk from one thread only. So my solution would be to have a lisp variable which contains the content to be displayed in the list box, which can be updated from any number of threads (of course those would have to work together of some sort not to have random content in that variable, but thats outside of LTk) and have the LTk thread update the list box from that variable. But as the LTk thread is waiting for Tk events, how to wake it up? The solution here is to have Tk create periodic events which are used for updates. Something like:
(defparamter *mylist* (list 1 2 3 4)) ;; this lists content is to be continously updated
(defun update (listbox) (unless *shutdown-gui* (listbox-clear listbox) (listbox-append listbox *mylist*) (after 1000 (lambda () (update listbox)))))
The after function gets passed a time in milliseconds and a function to call after the time has passed. You start the update process by calling update once, passing it the listbox to update (you might want to add some code to update only if the list has actually changed for efficiency...). This feature is quite nice for any kind of animations and very useful for background processing in LTk applications on Lisp implementations which are not multithreaded.
Peter
Thank you Peter; that is exactly what I needed.
On 12/14/10 2:37 AM, Peter Herth wrote:
Hi Kevin,
in general LTk has no support for multithreading. Mostly because threads are supported only by a few common lisp implementations and that updating a user-interface requires some synchronisation of some sort. Which Lisp implementation are you using? In the presence of multi-threading, I would strongly suggest to only communicate with Tk from one thread only. So my solution would be to have a lisp variable which contains the content to be displayed in the list box, which can be updated from any number of threads (of course those would have to work together of some sort not to have random content in that variable, but thats outside of LTk) and have the LTk thread update the list box from that variable. But as the LTk thread is waiting for Tk events, how to wake it up? The solution here is to have Tk create periodic events which are used for updates. Something like:
(defparamter *mylist* (list 1 2 3 4)) ;; this lists content is to be continously updated
(defun update (listbox) (unless *shutdown-gui* (listbox-clear listbox) (listbox-append listbox *mylist*) (after 1000 (lambda () (update listbox)))))
The after function gets passed a time in milliseconds and a function to call after the time has passed. You start the update process by calling update once, passing it the listbox to update (you might want to add some code to update only if the list has actually changed for efficiency...). This feature is quite nice for any kind of animations and very useful for background processing in LTk applications on Lisp implementations which are not multithreaded.
Peter
ltk-user site list ltk-user@common-lisp.net http://common-lisp.net/mailman/listinfo/ltk-user