SetValue on spinctrl doesn't send update event?

Jeff Shannon did write:

Jim Ursetto wrote:
>However, the event does not fire when I call SetValue on the spin
>control within the program.

The simplest way that I see doing this, is to put all of your
text-box-update code in a single parameter-less function/method, and
have EVT_SPINCTRL call that method.

This occurred to me as well, and is probably how I'll do it.
But see below.

A third option would be to create a custom composite control containing
both the spin control and the text box.

This is very interesting, and I hadn't thought of it. The problem is
that the spin/text box thing is just one example. For example, if I
have two windows, and a spin button in one needs to update a control in
the other, I don't think method #3 (composite control) will work.
Method #1--calling the text box update manually after a SetValue--would
still work in this case. But I want access to the spin button to be
transparent. This is especially important when another class has
programmatic access; it shouldn't have to change its behavior when I
connect a widget to the spin.

Thus, my suggestion to subclass the spin control, or at the least
having the frame or window class that contains it provide a method
to set its value. Outsiders would only deal with this method rather
than with the control itself. Of course, the problem with -this-
approach is that I have to do it to every widget I want this
behavior from.

In GTK, setting a value on a widget does send an event, consistently, so
I don't have to worry about this at all. So, I figured I was taking the
wrong approach in wxWindows, instead of the standard, idiomatic way.

I'd like to know what others have done in this situation. Do you guys
think I should ask on the wx-users list? Is there any code I can look
at? So far the closest thing I've found is in the wxPython demo.py; but
it was with the wxIntCtrl and wxTimeCtrl widgets, which actually do
manually generate and send their own update events after you set their
values programmatically. Just as in your suggested method #2.

Apologies for the long post, but I'm very curious.

ยทยทยท

--
"But if food is so good for you, how come the body
keeps trying to get rid of it?" -- breatharian.com
jim@3e8.org / 0x43340710 / 517B C658 D2CB 260D 3E1F 5ED1 6DB3 FBB9 4334 0710

Jim Ursetto wrote:

[...] The problem is
that the spin/text box thing is just one example. For example, if I
have two windows, and a spin button in one needs to update a control in
the other, I don't think method #3 (composite control) will work.
Method #1--calling the text box update manually after a SetValue--would
still work in this case. But I want access to the spin button to be
transparent. This is especially important when another class has
programmatic access; it shouldn't have to change its behavior when I
connect a widget to the spin.

Another possibility -- you might be able to set up idle processing which checks the status of your "watched" controls (the spincontrol) and then performs any needed updates on the slave control (textbox). Any time your app's event queue is empty, it would then ensure that the two controls were in sync. This could result in some minor sluggishness of response, since the textbox won't be updated immediately, but the lag time should be very small under most circumstances. There's a variety of sub-options here. You can unconditionally update your textbox every time the idle handler kicks in -- this is simplest, but results in a lot of unnecessary updates, which could become painful if updating is a bit slow, or if there's a lot of these control pairs. You could, then, track your "watched" controls' contents, and only update the textbox when those contents change. This will be more efficient at runtime, but requires a bit more coding. And if you're *really* motivated, you can do this as a fairly generic publish/subscribe (or Observer-like) pattern -- create a system that will allow you to register a callback that will be triggered when the value of a specified control changes. Then you could, say, call Observer.Register(spinctrl.Id(), textbox.Update()), which would add spinctrl to a list of watched controls and then call textbox.Update() when it changes. This Observer would check each control in its list at every idle event. You'd probably also want a way to Unregister controls, and there's all sorts of other features that could be added... This would be more work than just tracking one or two controls, but would probably be simpler if the number of watched controls is likely to be more than that (or if you'll need to do similar things in multiple applications).

Jeff Shannon
Technician/Programmer
Credit International