Reputation: 588
I want a function to create a LTK frame/canvas that lets it persist in the background. The function then updates the LTK frame/canvas through other functions as it does some other work.
What I have so far is the following two functions and one global variable:
(defvar *my-canvas*)
(defun initialize-window (...)
(with-ltk (:serve-event t )
(setq *my-canvas* (make-instance 'canvas))
(let ((c *my-canvas*))
...draw some objects on the canvas...
(pack c))
(defun update-window (...)
(with-ltk ()
(let ((c *my-canvas*))
...do something with the canvas...)))
I call these functions from a separate function:
(defun visualize (...)
... do something ...
(initialize-window ...)
... do something more ...
(update-window ...))
initialize-window
works without issues. But whenever I call the update-window
function, I run into a Tcl/Tk error: invalid command name ".wc"
error from (ltk::read-data)
called by any functions in the "do something with the canvas" part.
What is the recommended way to get update-window
to work without issues?
Upvotes: 1
Views: 99
Reputation: 588
Here's one way I was able to get it working.
It seems that the error Tcl/Tk error: invalid command name ".wc"
arises because the wish inside the with-ltk
in update-window
is different from that in the initialize-window
.
This can be seen in the call-with-ltk
code that the expansion of with-ltk
calls:
(defun call-with-ltk (thunk &rest keys &key (debug 2) stream serve-event remotep
&allow-other-keys)
"Functional interface to with-ltk, provided to allow the user the build similar macros."
(declare (ignore stream))
(flet ((start-wish ()
(apply #'start-wish
:remotep remotep
(append (filter-keys '(:stream :debugger-class :debug-tcl)
keys)
(list :debugger-class (debug-setting-condition-handler debug)))))
(mainloop () (apply #'mainloop (filter-keys '(:serve-event) keys))))
(let ((*wish* (make-ltk-connection :remotep remotep)))
(catch *wish*
(unwind-protect
(progn
(start-wish)
(multiple-value-prog1
(with-ltk-handlers ()
(with-atomic (funcall thunk)))
(mainloop)))
(unless serve-event
(exit-wish)))))))
A work-around is to do this handling yourself. We base our code upon the above code:
(defun initialize-window (...)
(unless (wish-stream *wish*) (start-wish))
(catch *wish*
... do something with the canvas or GUI ...
... but do not call (start-wish) or (exit-wish) ...)))
(defun update-window (...)
(catch *wish*
... do something with the canvas or GUI ...
... but do not call (start-wish) or (exit-wish) ...))
However, if the plan is to call visualize
repeatedly, then we also need a finalize-window
function that exits the wish:
(defun visualize (...)
(unwind-protect
(progn
... do something ...
(initialize-window ...)
... do something more ...
(update-window ...))
(finalize-window)))
with its definition as:
(defun finalize-mot-window ()
(catch *wish*
(exit-wish))))
Upvotes: 2