Hmm. I'd not encountered any problems with snapping the graph; the image size always seemed to be the same as the original screen size.
Then a thought occurred to me.... I speculated that perhaps you were creating your graph, populating it with data, and then snapping it before ever dropping into the event loop and giving it a chance to display. This can often cause problems with widgets, because many widgets wait until reaching the event loop before rendering. This is actually much more efficent than rendering immediately, especially if you make several configuration changes to the widget. I wouldn't be at all surprised if the graph widget were deferring rendering until the event loop, especially given the amount of information it commonly displays.
I tested this assumption out, and it seems to be the case. When I create a graph, put data on it, and then immediately snap, I sometimes get oddly sizes GIF images. But if I wait until after I've entered the event loop, then my snap is properly sized. This is illustrated by the following code:
Code:
package require BLT
namespace import blt::*
vector create x(20)
vector create y(20)
x seq 1 20
y random
graph .g
pack .g -expand yes -fill both
.g element create data -xdata x -ydata y
set i [image create photo]
.g snap $i
$i write -format gif init1.gif
image delete $i
update
set i [image create photo]
.g snap $i
$i write -format gif init2.gif
image delete $i
I found that the image in
init1.gif was not properly sized, but that the image in
init2.gif -- after the call to
update to process any outstanding events -- is properly sized.
How to solve this then depends on your application. For a truly interactive program, I would typically give the user some method for saving the graph as desired, for example, via a menu selection:
Code:
set types {
{ {GIF Files} {.gif} }
{ {GIF Files} {} GIFF }
{ {All Files} * }
}
proc saveGraph {w} {
set filename [tk_getSaveFile -filetypes $::types]
if {$filename != ""} {
set i [image create photo]
$w snap $i
$i write -format gif $filename
image delete $i
}
}
menu .mbar
. configure -menu .mbar
.mbar add cascade -label "File" -underline 0 -menu .mbar.file
menu .mbar.file -tearoff 0
.mbar.file add command -label "Save As..." -underline 0 -accelerator "Ctrl+S" -command {saveGraph .g}
.mbar.file add command -label "Quit" -underline 0 -accelerator "Ctrl-Q" -command {exit}
bind . <Control-KeyPress-s> {.mbar.file invoke "Save As..."}
bind . <Control-KeyPress-q> {.mbar.file invoke "Quit"}
If, for some reason, the user isn't allowed to interact with the program, you'll need to make sure you enter the event loop after creating or changing a graph and before snapping it. The quick and dirty way -- as long as you're
sure there won't be any problems with events that might already be on the event queue -- is to call
update, like I did above.
- Ken Jones, President, ken@avia-training.com
Avia Training and Consulting,
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax