[ltk-user] Button/Sender associated with Event?

Peter Herth herth at peter-herth.de
Sun Feb 5 14:03:15 UTC 2006


Hi Eric,

On 2/5/06, Eric Hochmeister <erichochmeister at gmail.com> wrote:
> Hi,
>
> The functionality I'm looking for is that I want to set a button's
> action to be a function.  When the function is called, I want to know
> which button called it.  This is because many buttons can be linked to
> the same function.  How do I accomplish this?

I wonder why you need to know that and cannot know yet... usually, at
the place where I define callbacks or event functions, the widget or
the application which has a reference to the widget is in the lexical
scope, so the callbacks can just close over it. So far, this was
enough for all of my needs.

> I looked at the docs for :command and it seems like they only pass
> "values" to the function.  (what was changed, etc.)
>
> So I figured, maybe I need to look at binding, it seems to send out an
> event.  So I tried it, and I noticed this...
>
> radio button value = NILl:(:EVENT "w13" 13 16 ?? ?? ?? ?? 273 324 1)<=
> event = #S(LTK:EVENT :X 13 :Y 16 :KEYCODE ?? :CHAR ?? :WIDTH ??
> :HEIGHT ?? :ROOT-X 273 :ROOT-Y 324 :MOUSE-BUTTON 1)
>
> The Tcl representation seems to have access to the widget that caused
> the event ie. "w13" but the lisp representation doesn't.  I looked at
> the structure for event and this indeed seems to be the case.
>
> (defstruct event
>   x
>   y
>   keycode
>   char
>   width
>   height
>   root-x
>   root-y
>   mouse-button
>   )
>
> So now I'm puzzled.
>
> Is there any way to accomplish the functionality I'm looking for??
> (other than hacking up my own way with functions which emulate this?)
> I must be missing something.

We could consider putting the widget creating the event in the event
structure, if that is needed. As you have seen correctly, the name of
the widget is available, we would need to have a hashtable around to
get the widget object from that name. But look at my radio-button
example to see how I solve this usually.

> Also, another side question.  I'm playing around with radio buttons
> and I was trying to figure out how to get the state to be on or off..
> and by state I mean whether the radio button is selected or not (ON or
> OFF).  From what I can tell, if the :value of a radio button is nil,
> then it's ON.  If it has any other value than nil then its OFF.  Is
> this right??  Its just puzzling me cause it seems so unintuitive.

Well, radio-buttons are not extremely elegant, but here is how you use them:
When you create a radio-button, you pass 2 important arguments
"variable" the name of the radio button group to build, and "value"
the value the variable contains if the radio-button has been selected.
 I modified ltktest to give a simple radio-button example:

      (let* ((bar (make-instance 'frame))
             (fradio (make-instance 'frame :master bar))
             (leggs (make-instance 'label :master fradio :text "Eggs:"))
             (r1 (make-instance 'radio-button :master fradio :text
"fried" :value 1 :variable "eggs"))
             (r2 (make-instance 'radio-button :master fradio :text
"stirred" :value 2 :variable "eggs"))
             (r3 (make-instance 'radio-button :master fradio :text
"cooked" :value 3 :variable "eggs"))
	     (fr (make-instance 'frame :master bar))
	     (lr (make-instance 'label :master fr :text "Rotation:"))
	     (bstart (make-instance 'button :master fr :text "Start" :command
'start-rotation))
	     (bstop  (make-instance 'button :master fr :text "Stop"  :command
'stop-rotation))
    .....

	(pack bar :side :bottom)
        (pack (list fradio leggs r1 r2 r3) :side :left)
        (dolist (r (list r1 r2 r3))
          (let ((button r))
            (setf (command r) (lambda (val)
                                (declare (ignore val))
                                (eggs button)))))

and finally the event handling fuction:

(defun eggs (radio)
  (format t "Prepare ~a eggs.~%"
          (case (value radio)
            (1 "fried")
            (2 "stirred")
            (3 "cooked")))
  (finish-output))

The variable argument can be an arbitrary string, as long as all the
radio buttons in that group have the same one. Of course, I could just
have passed value to the function eggs, but I wanted to demonstrate,
how you get access to the widgets.

Peter



More information about the ltk-user mailing list