[tkinter] widget size adjustment

Rick Johnson rantingrickjohnson at gmail.com
Tue Jun 21 12:48:02 EDT 2016


On Sunday, June 19, 2016 at 1:29:11 PM UTC-5, Pierre-Alain Dorange wrote:
> I got a small interface handle with tkinter / Gridmanager.
> I configure row and column to follow user window size
> adjustement, that' fine. but i do not know how to adjust
> the main widget : a canvas displaying a portion of a big
> image. I bind a resize event that works, but do not know
> what to do from that.
>
> Any clue or advice or tutorial ?

I'm sorry, but your explanation is lacking, and could be
the reason you have not received help so far. I'll attempt
to guess what the problem is, and then you can refine the
question if none of these solutions is what you're looking
for.

(1) If you want a widget to fill *ALL* of the available space
within it's parent window, you'll need to set the
appropriate options for the "pack" or "grid" geometry
manager -- depending on which one you are using. Note: i
won't bother discussing the "place" manager. (See CODE1 and
CODE2 below)

  Pro tip: If your top-window *ONLY* contains a single child
  widget that fills the entire space, *ALWAYS* use pack!
  
(2) If the contents of your canvas exceed the viewable
portion of it's viewable area, then you'll need to add
scroll-bars and set the scrollregion option so that you can
view the "clipped portions". (See CODE3 below)

(3) Or perhaps you want the canvas content(s) to resize
dynamically as the canvas expands and contacts?

(4) Something else entirely...?

============================================================
 CODE EXAMPLES
============================================================

## BEGIN: CODE1 ##
import Tkinter as tk
from Tkconstants import *
root = tk.Tk()
canvas = tk.Canvas(root, bg='red')
canvas.pack(fill=BOTH, expand=YES, padx=5, pady=5)
root.mainloop()
## END: CODE1 ##

## BEGIN: CODE2 ##
import Tkinter as tk
from Tkconstants import *
root = tk.Tk()
root.rowconfigure(1, weight=1)
root.columnconfigure(1, weight=1)
canvas = tk.Canvas(root, bg='red')
canvas.pack(fill=BOTH, expand=YES, padx=5, pady=5)
root.mainloop()
## END: CODE2 ##

## BEGIN: CODE3 ##
import Tkinter as tk
from Tkconstants import *
#
ROOT_MSG = """\
In the two windows below, observe the consequences of the canvas
"scrollregion" option. The left window has scollregion set to contain
the entire contents, whilst the right window has not configured the
scrollregion at all, and as a result, the scrollbars are useless.
"""
#
class MyCanvas(tk.Canvas):
    def __init__(self, master, **kw):
        self.frame = tk.Frame(master)
        self.frame.rowconfigure(0, weight=1)
        self.frame.columnconfigure(0, weight=1)
        self.hbar = tk.Scrollbar(self.frame, orient=HORIZONTAL)
        self.block = tk.Frame(self.frame, width=18, height=18)
        self.block.grid(row=1, column=1)
        self.vbar = tk.Scrollbar(self.frame, orient=VERTICAL)
        tk.Canvas.__init__(self, self.frame, **kw)
        tk.Canvas.grid(self, row=0, column=0, sticky=N+S+E+W)
        self.hbar.configure(command=self.xview)
        self.vbar.configure(command=self.yview)
        self.config(yscrollcommand=self.vbar.set,
                    xscrollcommand=self.hbar.set)
        self.hbar.grid(row=1, column=0, sticky=W+E)
        self.vbar.grid(row=0, column=1, sticky=N+S)
#
def fill_canvas_with_junk(canvas):
    sx = 5
    for r_ in range(10):
        canvas.create_rectangle(sx, 5, sx+100, 3000, fill='gray')
        canvas.create_line(sx, 5, sx+100, 3000)
        sx += 200
#
root = tk.Tk()
root.geometry('+5+5')
root.title('RootWindow (aka: BWFL)')
w = tk.Label(root, text=ROOT_MSG, fg='red')
w.pack(fill=BOTH, expand=YES)
#
top1 = tk.Toplevel(root)
top1.geometry('400x300+5-50')
top1.title('Example1 (clipped regions accessable)')
canvas1 = MyCanvas(top1, bg='white')
canvas1.frame.pack(fill=BOTH, expand=YES, padx=5, pady=5)
fill_canvas_with_junk(canvas1)
sx,sy,ex,ey = canvas1.bbox(ALL)
canvas1['scrollregion'] = (0,0,ex+5,ey+5)
#
top2 = tk.Toplevel(root)
top2.geometry('400x300-5-50')
top2.title('Example2 (clipped regions *NOT* accessable)')
canvas2 = MyCanvas(top2, bg='white')
canvas2.frame.pack(fill=BOTH, expand=YES, padx=5, pady=5)
fill_canvas_with_junk(canvas2)
#
root.mainloop()
## END: CODE3 ##

PS: Hopefully there's no bugs in here :-)


More information about the Python-list mailing list