Please help -- Tkinter Scale widget with DoubleVar is acting weird
Hi all. I'm currently using a Tkinter Scale widget which uses a DoubleVar as its control variable. I then use the "trace_variable('w', callback)" method to invoke a callback whenever the DoubleVar changes. The problem is this: the callback is triggered when the slider moves (as it should), but it's also triggered when I just HOVER the mouse over the slider without clicking! Somehow or other, it must think that the control variable is being changed, even though it isn't. I *think* that this problem is related to the loss of precision that DoubleVars can have, but I'm not really sure. Has anyone else experienced this problem? How can I fix this? As an aid, here's a quick stub program that illustrates the problem. Try (for example) moving the slider to 0.3, release the mouse button, then move the mouse pointer back and forth over the slider WITHOUT clicking. Each time the pointer passes over the slider, it will print the value. import sys, Tkinter, types root = Tkinter.Tk() var = Tkinter.DoubleVar() def callback(*args): print var.get() var.trace_variable("w", callback) slider = Tkinter.Scale(root, from_ = 0.0, to = 1.0, resolution = 0.1, variable = var, orient = 'horizontal') slider.grid(sticky='ew') root.mainloop()
On Thu, 19 Aug 2004 11:32:56 -0400 "Jared Cohen" <Jared.Cohen@noaa.gov> wrote:
Hi all. I'm currently using a Tkinter Scale widget which uses a DoubleVar as its control variable. I then use the "trace_variable('w', callback)" method to invoke a callback whenever the DoubleVar changes.
The problem is this: the callback is triggered when the slider moves (as it should), but it's also triggered when I just HOVER the mouse over the slider without clicking! Somehow or other, it must think that the control variable is being changed, even though it isn't. I *think* that this problem is related to the loss of precision that DoubleVars can have, but I'm not really sure. Has anyone else experienced this problem? How can I fix this?
As an aid, here's a quick stub program that illustrates the problem. Try (for example) moving the slider to 0.3, release the mouse button, then move the mouse pointer back and forth over the slider WITHOUT clicking. Each time the pointer passes over the slider, it will print the value.
import sys, Tkinter, types
root = Tkinter.Tk() var = Tkinter.DoubleVar()
def callback(*args): print var.get()
var.trace_variable("w", callback)
slider = Tkinter.Scale(root, from_ = 0.0, to = 1.0, resolution = 0.1, variable = var, orient = 'horizontal') slider.grid(sticky='ew')
root.mainloop()
Hi Jared, that's interesting, I never noticed this behavior, probably because I used callbacks where excess calls didn't matter. To avoid excess calls to your callback() you might consider to store the value of var in a second variable like this: var = Tkinter.DoubleVar() oldvalue = var.get() def callback(*args): global oldvalue if var.get() != oldvalue: oldvalue = var.get() print var.get() I hope this helped Michael
I do *not* see this behavior on fedora-release-2-4 (Fedora Core 2 Linux) python-2.3.3-6 tcl-8.4.5-7 tk-8.4.5-6 However, while dragging I can see a set to the same value multiple times. I suppose this happens when the mouse movement is too small to move one "resolution" unit. You could use a class which acts as a function wrapper to eliminate the redundant calls to "callback": class RedundancyEliminator: def __init__(self, var, callback): self.var = var self.callback = callback self.lastval = var.get() def __call__(self, *args): newval = var.get() if newval != self.lastval: self.lastval = newval return self.callback(*args) return None def callback(*args): print var.get() var.trace_variable("w", RedundancyEliminator(var, callback)) Jeff
I looked into this some more, and was able to reproduce the problem using tcl-8.3.5-88 redhat-release-9-3 I was then also able to demonstrate it on tcl/tk 8.5. I used this wish script: scale .s -variable v -resolution 0.1 -from 0 -to 1 trace variable v w changed proc changed {args} { global v; puts "v changed. new value: $v" } pack .s I set the scale value to 0.7. Now, by moving the cursor *between the slider and the trough*, I get the repeated message "v changed. new value: 0.7". (It's the movement between slider and trough, not just hovering, that made the redundant sets happen for me) This behavior doesn't seem to depend on the value of tcl_precision. It *looks* like the problem is in TkRoundToResolution(). It returns a slightly different value than the incoming value, so that the test "scalePtr->value == value" in tkUnixScale:TkpSetScaleValue() fails and it falls through to a Tcl_SetVar call. This is low-level stuff inside of tk. Like Fredrik suggested, your next step is to go to the tcl/tk community with your report, if it's important to you. Jeff
participants (3)
-
Jared Cohen -
Jeff Epler -
Michael Lange