Reputation: 8941
I have a canvas widget which shows a gradient. This is done by drawing lines from its top to bottom each with a slightly different color. To achieve this, in the function that draws the line I check the height of the canvas and draw lines according to it. The problem is, that the first time its drawn, or when the widget is resized (when it's resized, I call the drawing function) the result I get from the command winfo height $legendCanvas
is wrong and the drawing is bad, only when I recall the function again, it gets the right value and the drawing results are good. I've tried adding update idletasks
at the start of the method, it doesn't work.
The relevant canvas is called legendCanvas
itcl::body siReportAttackersMatrix::setThreshold {{val ""}} {
update idletasks
# some unrelated code here
# ...
#redraw the legend
$legendCanvas delete line all
set range [expr {$maxVal*1.0-$minVal}]
set step [expr {$range/[winfo height $legendCanvas]}]
for {set y 0} {$y < [winfo height $legendCanvas]} {incr y} {
# some unrelated code that calculated the color
set id [$legendCanvas create line 0 $y [winfo width $legendCanvas] $y -fill $color]
}
set textX [expr {[winfo width $legendCanvas]/2}]
set id [$legendCanvas create text $textX 0 -anchor n -text [expr {int($maxVal * 1000)}]]
set id [$legendCanvas create text $textX [winfo height $legendCanvas] -anchor s -text [expr {int($minVal * 1000)}]]
foreach fraction [list 2 4 [expr {4/3.0}]] {
set textY [expr {int([winfo height $legendCanvas]*1.0/$fraction)}]
set textValue [expr {int(($maxVal-$minVal)*(1-1.0/$fraction)*1000)}]
set id [$legendCanvas create text $textX $textY -anchor center -text $textValue]
}
}
in order to conserve space I've removed code that is irellevent to the problem, like calculating the color, some more functions that the method does and bindings on the different items in the canvas
Screen pics of the results:
On creation (on the left), After recalling the method(on the right):
On resize (on the left), After recalling the method (on the right):
Upvotes: 1
Views: 1021
Reputation: 137587
The simplest way of fixing this is to recompute the gradient whenever that canvas widget receives a <Configure>
event. In particular, the %h
and %w
substitutions in the <Configure>
event tell you what the size of the widget is being set to, though the basic Tk infrastructure will also save those values into the widget record (where winfo height
and winfo width
can retrieve them).
# Something like this; you might want to tweak the binding
bind $legendCanvas <Configure> { doRescale %W %w %h }
You're advised to have a procedure (or method) that just handles this; other operations that require the rescaling (such as the initial setup code) can just call it as necessary.
Upvotes: 3