Tkinter Canvas/Grid question

G

Gary Richardson

Is there a simple way of causing the size of a canvas to change as the
window is resized when using the Grid geometry manager? Setting
sticky='NESW', as in the following code, doesn't work though the
documentation for Grid seems to imply that it should: "sticky If a
slave's cell is larger than its requested dimensions, this option may be
used to position (or stretch) the slave within its cell. ... The sticky
option subsumes the combination of anchor and fill that is used by
pack". Or is there something wrong with my code?

Thanks,
Gary Richardson

from Tkinter import *

class Test(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
frame = Frame(parent)
self.canvas = Canvas(frame, bg='white' , width=300, height=100)
self.canvas.grid(row=0, column=0, sticky='NESW')
frame.grid()

root = Tk()
Test(root)
root.mainloop()
 
M

Michael Peuser

Hi Gary
from Tkinter import *

class Test(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
frame = Frame(parent)

There is some confusion here: self *is* the frame, no need or use to make
another....
self.canvas = Canvas(frame, bg='white' , width=300, height=100)

There is some trick needed here: add:
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
self.canvas.grid(row=0, column=0, sticky='NESW')
frame.grid()
This packs the frame to the parent, so it limits the size of your frame in
any case
I should recommend pack in this place (which is possible, because it's
another frame)

Altogether it shall look as follows and work fine:

def __init__(self, parent):
Frame.__init__(self, parent)
self.pack(fill=BOTH,expand=1)

self.canvas = Canvas(self, bg='white' , width=300, height=100)
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
self.canvas.grid(row=0, column=0, sticky='nesw')
 
J

Jeff Epler

To expand on Michael Peuser's response, I'll explain a little more. The
grid first calculates the size requested by each item to find the
requested size for each row and column. When there are no rowspans,
the requested size for a row is the maximum of the requested sizes for
any item in that row. The same holds when talking about columns, their
weights and their widths.

Then, when there is too much or too little space, the difference is
split up among the rows according to their weight. The default weight
for a row is 0. Let total_weight be the sum of the weight of each row
with a widget, and diff be the number of pixels difference between the
height of the frame and the sum of the requested heights of its rows. If
total_weight is 0, then all rows get their requested height. Otherwise,
each row gets diff*row_weight/total_weight, with something done about
the rounding errors.

That's why the short answer to set the weight of row and column 0 to 1
works.

The other problem you may run into (I haven't run your code, but with
many levels of widget present, this may be a problem) is that each
level of the widget tree between this one containing the canvas, and the
Toplevel() or Tk() above it, must also be configured so that they will
expand to consume any extra available space. Otherwise, the condition
"when there is too much or too little space" can't be true, because the
widget won't be given a larger size than it requested.

Jeff
 
M

Michael Peuser

"Jeff Epler" <[email protected]>

Thank you for the comprehensive explanations you gave I was to lazy to do
;-)
In addition I should like to point out a chapter from Nancy Walsh's book
"Learning Perl/Tk" where one can find a lot of information about the
different geometry managers (no prejudices against Perl I hope?)
http://www.oreilly.com/catalog/lperltk/chapter/ch02.html
The other problem you may run into (I haven't run your code, but with
many levels of widget present, this may be a problem) is that each
level of the widget tree between this one containing the canvas, and the
Toplevel() or Tk() above it, must also be configured so that they will
expand to consume any extra available space

This had been one of the problems, so I suggested to use an appropriate
paramtrized pack on the higher level for simplicity.

Kindly
Michael P
 
G

Gary Richardson

[snip]


Michael, Jeff,

Thanks for your replies. I made the changes indicated above and the resizing
works just fine now. I'm still puzzled as to why pack() would be used with
the frame and grid() used with the canvas, and other widgets, I suppose. I
was under the impression that only a single geometry manager should be used
in a program. I guess the rule is: a single geometry manager must be used
within a frame and its descendants. Is that correct?

Thanks,
Gary Richardson
 
M

Michael Peuser

Gary Richardson said:
Michael, Jeff,

Thanks for your replies. I made the changes indicated above and the resizing
works just fine now. I'm still puzzled as to why pack() would be used with
the frame and grid() used with the canvas, and other widgets.

No, no! I just use pack() because it is much simpler and you made no
constraints as to how to show the frame in the toplevel.. There is a lot of
useful information in that chapter from Nacy Welsh's book

......
was under the impression that only a single geometry manager should be used
in a program. I guess the rule is: a single geometry manager must be used
within a frame and its descendants. Is that correct?

Nearly. You can freely choose the g.m. in EVERY frame (but then stick to it
in THAT frame)

Kindly
Michael P
 
J

Jeff Epler

You can manage any widget with any geometry manager. (You can even grid
a button inside of a label, but god knows why you'd want to)

Sometimes you must use "grid" to get proper layout. For instance, if
you want to create a scrolled item (canvas or text) with horizontal and
vertical scrollbars, this is the only sane way to do it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top