I am using Tk as the GUI for a Common Lisp app. My code kinda likes to
stay on top of even a GUI, so (one example) I want to know every time an
entry widget value is changed by the user, keystroke by keystroke. "on
change notification", basically.
All I could think of (and it seems to be working, but I sense there is a
more direct way) is to specify :validate key and :validateCoomand which
really just wrote :callback into the socket, along with other info (an
arbitray id generated in Lisp, and I threw in %P to get the text at the
same time):
"puts {:callback .W3.W10.ENTER-ME.VCMD %P}; return 1;"
That worked, praise McCarthy, except the string is capitalized.
(a) Am I crazy?
(b) What am I doing that makes the text come back capitalized?
Thx,
kenny
and that worked as I expected.
Can you show us a bit more of the code?
Regards,
Arjen
Sorry, it was library code on my side, doing the normal Lisp
case-insensitive "thing" and converting everything to uppercase.
Lisp could read preserving case, but the case insensitivity thing is
actually nice, so... the trick I just learned (from other library code
-- bless open source) is to have Tk wrap text in double-quotes to
preserve case.
Thx, kenny
Regards,
Arjen
Bruce
No prob. But one question has gone unanswered: is this the only way to
get notified by Tk of every change to the entry value /during editing/,
ie, before they exit the field?
pack [entry .e -validatecommand {puts "%P"; return 1} -validate key]
Not that validateCommand is a bad way to do it, but I just keep thinking
there must be a simple change notification I am missing. I have a
textVariable associated with the widget, but I am not sure that helps. I
looked at binding keyevents but that seems global, not widget specific.
Could be wrong on that, Tk is all new to me.
thx, kt
Kenny Tilton wrote:
> Bruce Hartweg wrote:
>
>> Glad you found the answer, and thanks for posting the follow-up
>> so we all aren't still sitting around scratching our heads ;)
>
>
> No prob. But one question has gone unanswered: is this the only way to
> get notified by Tk of every change to the entry value /during editing/,
> ie, before they exit the field?
>
> pack [entry .e -validatecommand {puts "%P"; return 1} -validate key]
>
> Not that validateCommand is a bad way to do it, but I just keep thinking
> there must be a simple change notification I am missing. I have a
> textVariable associated with the widget, but I am not sure that helps. I
> looked at binding keyevents but that seems global, not widget specific.
> Could be wrong on that, Tk is all new to me.
>
> thx, kt
>
you could use bindings, they can be done per widget (or widget class,
or some groups of widgets you care about) but for an entry the validate
cmd is the easiest as all of the bindings are done for you already.
One note to make here is that by using validate -key this will capture
the user typeing into the entry, but if the system supports it (like X11)
then a user could use a mouse paste action to modify the entry and it
wouldn't go thru your extra handling. one way to fix that is to use validate
-all which should catch any edits.
Another option you have is setting a write trace on the variable associated
with the entry. WARNING - if you do this be careful if you are mixing variable
traces and validation in the same widget - you can easily get things screwed up
should be fine if you are doing either one or the other though, and which way
that is is a personal preference.
Bruce
> No prob. But one question has gone unanswered: is this the only way to
> get notified by Tk of every change to the entry value /during editing/,
> ie, before they exit the field?
>
> pack [entry .e -validatecommand {puts "%P"; return 1} -validate key]
>
> Not that validateCommand is a bad way to do it, but I just keep thinking
> there must be a simple change notification I am missing.
What could be more simple than using -validatecommand? Why do you see
that as a complicated solution? Your type of problem is precisely why
-validatecommand exits -- to be notified of changes during editing.
Stick with that -- it's simple and it works. If it's not behaving how
you expect or need, tell us what it's not doing that you want it to do
and I'm sure we can help.
Your other choices are to put a trace on the variable associated with
the entry widget, or do a whole lot of work mucking with bindings.
Neither of those seem as simple as using the built-in validation
features of the entry widget.
--
Bryan Oakley
http://www.tclscripting.com
Wow, I sure missed that. The doc could not be clearer! I must have
panicked when I read something about a binding being for a window -- I
have never gotten use to the X model in which every widget is a window.
>
> One note to make here is that by using validate -key this will capture
> the user typeing into the entry, but if the system supports it (like X11)
> then a user could use a mouse paste action to modify the entry and it
> wouldn't go thru your extra handling. one way to fix that is to use
> validate
> -all which should catch any edits.
Oops. I remember reading that, too. Thx.
>
> Another option you have is setting a write trace on the variable associated
> with the entry. WARNING - if you do this be careful if you are mixing
> variable
> traces and validation in the same widget - you can easily get things
> screwed up
> should be fine if you are doing either one or the other though, and
> which way
> that is is a personal preference.
Wow, TRACE is one I missed. Looks perfect. I was just getting ready to
do a binding for the <<modified>> virtual event. Any difference (or is
my guess right that TRACE WRITE is implemented using <<modified>>?
ken
uh-oh. I have an Entry widget, <<Modified>> is documented as being for
Text widgets. No wonder it did not work. :) Lemme try TRACE...
ken
> One note to make here is that by using validate -key this will capture
> the user typeing into the entry, but if the system supports it (like X11)
> then a user could use a mouse paste action to modify the entry and it
> wouldn't go thru your extra handling. one way to fix that is to use validate
> -all which should catch any edits.
This is not true on any system I know about. Pasting text with the
mouse does trigger "key" validation.
The big difference with "all" validation is that it validates
behind-the-scenes changes to the textvar variable, and calls the
type of change "forced".
--
Donald Arseneau as...@triumf.ca
Not so much complicated as "vaguely disquieting". :) And I was fully
prepared to hear "Yup, that is how we do it." But...
One sign that I was barking up the wrong tree was that my first attempt
failed because the write-back (to Common Lisp) I had as the
validateCommand did not return a boolean, so TCL rightly squawked. I had
to add "return 1".
That kind of thing always makes me nervous, as well as the simple fact
that I did not want to validate the field, I wanted to mirror it
dynamically in Lisp, propagating changes to other dependent fields
automatically. (I have a neat dataflow hack I use to make GUIs way
cool.) So just the /name/ "validateCommand" bothered me (I think like
that <g>).
A serious objection is that I am actually developing a library for
general use. The dataflow thing is meant to be behind the scenes. By
using validateCommand for my behind-the-scenes trickery, I take that
away from the user who might want to use it for actual validation. I
could probably work out a way to give them validateCommand and still get
the dataflow supported, but you (and Bruce?) gave me a better idea: trace.
That was tough to get working. My library is an engine that shoots
snippets of code over to TCL in a somewhat random order. I see TCL does
not like that. My original order turned out to be:
-make an entry
-trace the entry qua variable
-configure the entry to be its own text variable
-set the entry qua text variable
-configure the text attribute of the entry (!)
I was about to ask here why I got only one trace message when I guessed
the order was killing me. Now I:
-make an entry with its own path as the textvariable
-trace the entry qua variable
-set the entry qua variable to any initial string
-do /not/ configure the text attribute!
That (touch wood) works. :)
Thanks to all.
ken
Well now, that is entirely a different question. No, you don't want to
use the -validatecommand stuff to mirror a variable. Variable traces are
more suited to this. When asking for advice, be sure you explain what
you're really trying to do...
> ...
> A serious objection is that I am actually developing a library for
> general use. The dataflow thing is meant to be behind the scenes. By
> using validateCommand for my behind-the-scenes trickery, I take that
> away from the user who might want to use it for actual validation. I
> could probably work out a way to give them validateCommand and still get
> the dataflow supported, but you (and Bruce?) gave me a better idea: trace.
If you had stated all that up front I'm sure all the advice you were
given would have been totally different.
You are on the right track with the variable traces. I'd recommend,
however, instead of using a global variable named after the widget
(which takes that option away from the user), use a namespace variable
instead. Arrays are a bit easier to use than computed variable names so
I'd recommend a single namespace array indexed by widget name, to wit:
namespace eval mypackage {
variable data
entry .whatever -textvariable data(.whatever) ...
You mean like my original post?:
"I am using Tk as the GUI for a Common Lisp app. My code kinda likes to
stay on top of even a GUI, so (one example) I want to know every time an
entry widget value is changed by the user, keystroke by keystroke. "on
change notification", basically. "
<g> Thanks for the tip on namespaces.
ken