[Tutor] 1 or 2 Tkinter Canvas questions

Michael Lange klappnase at freenet.de
Tue Mar 9 19:54:13 EST 2004


Hi, Gregor,


On Tue, 09 Mar 2004 14:57:47 +0100
Gregor Lingl <glingl at aon.at> wrote:


> Recently I wrote a simple Tkinter program
> example which should draw a maximal rectangle
> on a (resizable) Canvas. It goes essentially
> like this:
> 
> from Tkinter import *
> 
> class RedRect(Tk):
>    def __init__(self):
>        Tk.__init__(self)
>        self.title("RedRect")
>        CvRedRect(self).pack(expand=1, fill="both")
> 
> class CvRedRect(Canvas):
>    def __init__(self, root):
>        Canvas.__init__(self, root, bg="white")
>        self.bind("<Configure>", self.paint)
>        self.r = self.create_rectangle(0,0,0,0, outline="red")
>        self.txt1 = self.create_text(30,30,text="")
>        self.txt2 = self.create_text(30,60,text="")
>    def paint(self, event):
>        w,h=event.width, event.height
>        self.itemconfig(self.txt1, text=str(w))
>        self.itemconfig(self.txt2, text=str(h))
>        self.coords(self.r,2,2,w-3,h-3)
> 
> if __name__ == "__main__":
>    RedRect().mainloop()   # Marilyn's idea, nice!
> 
> Now my questions:
> 
> (1) Why do I have to use in
>        self.coords(self.r,2,2,w-3,h-3)
>    the constant(s)  2 and 3? One would expect, that
>    something like
>        self.coords(self.r,0,0,w-1,h-1)
>    or
>        self.coords(self.r,0,0,w,h)
>    would work. But no, these rectangles are outside
>    the visible prtion of the canvas. Moreover: is
>    there some property ("option") of canvas which
>    represents this sort of "inset"?
> 

I changed the 2 and 3 in your code to 1 and 2 and still got the rectangle visible;
obviously that's the width of the rectangle' lines(for x0/y0 1 pixel, for x1/y1 2 pixels, because
you must add the width of the left and right / top and bottom lines).
Obviously x0/x1/y0/y1 determine the coordinates of the rectangle *inside* the red rectangle we see.
(with x1/y1 as width and height of the rectangle)
That's why the option is called "OUTline" - it's outside the rectangle.

I added a test to your paint method:

   def paint(self, event):
       w,h=event.width, event.height
       print w, h, self['width'], self['height']
       self.itemconfig(self.txt1, text=str(w))
       self.itemconfig(self.txt2, text=str(h))
       self.coords(self.r,1,1,w-2,h-2)

The result when I start the program:

[pingu at localhost pingu]$ /usr/local/share/test3.py
297 209 295 207

Obviously the Canvas gets larger when the rectangle is created; the difference is even
the same if you change the rectangle's width to 0 !
I guess we'll just have to get used to that.

>    Shortly: why doesn't appear the whole Canvas on the
>    screen?
> 
> (2) Why does apparently
>        self.geometry("400x300+50+50")
>    determine the size of the canvas packed into the
>    Tk() - window and not the sizue of the Tk-window
>    it*self*, which is 408*327 pixels?
> 

I think the answer is obvious: you determine the geometry of the part of the window you can use - the container
and not the geometry of your window manager's border decoration.

> Minor questions, maybe. But I find it annoying that I need
> *experiment* with canvas and rectangle in order to get it as
> wanted. I'd prefer to compute it over trial an error.
> 

I haven't done much on Tkinter Canvasses yet, but I am not sure if the Canvas/rectangle behavior
which might look like a *bug* here could be a *feature* in some cases.


I hope this helped

Michael




More information about the Tutor mailing list