0

The TkDocs website is a great resource, but it is not complete. The manpage is complete, but of course does not document Python bindings. " How to get the screen size in Tkinter? " points out that the window size can be obtained using root.winfo_screenwidth() / root.winfo_screenheight(), but that addresses only the full window, not individual cells within a grid.

Using the TkDocs code as an example, how can I find the height of, e.g., the third row so that I can set a minsize that prevents the buttons from being hidden? Nothing I've tried using bbox() or grid_bbox() returns anything other than (0,0,0,0). What is the proper syntax for returning an actual size?

----- Edit -----

The code now shows how bbox() is used within routines called from the event loop, returning correct values.

from tkinter import *
from tkinter import ttk

# bbox() works after window has been rendered
def e_config(event):
    w, h = event.width, event.height
    print("Resize: content", w, "x", h)
    print("content bbox=", content.bbox())

def OK():
    print("OK: winfo, bbox:")
    print("    root: ", root.winfo_width(), root.winfo_height(), root.bbox())
    print(" content: ", content.winfo_width(), content.winfo_height(), content.bbox())
    print("   frame: ", frame.winfo_width(), frame.winfo_height(), frame.bbox())

root = Tk()

content = ttk.Frame(root, padding=(5,5,12,12))
content.bind("<Configure>", e_config)

frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100)
namelbl = ttk.Label(content, text="Name")
name = ttk.Entry(content)

onevar = BooleanVar()
twovar = BooleanVar()
onevar.set(True)
twovar.set(False)

one = ttk.Checkbutton(content, text="One", variable=onevar, onvalue=True)
two = ttk.Checkbutton(content, text="Two", variable=twovar, onvalue=True)
ok = ttk.Button(content, text="Okay", command=OK)
cancel = ttk.Button(content, text="Cancel")

content.grid(column=0, row=0, sticky=(E, W))    # Don't resize vertically
frame.grid(column=0, row=0, columnspan=3, rowspan=2)
namelbl.grid(column=3, row=0, columnspan=2)
name.grid(column=3, row=1, columnspan=2)
one.grid(column=0, row=3)
two.grid(column=1, row=3)
ok.grid(column=3, row=3)
cancel.grid(column=4, row=3)

root.configure(bg="#234")
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
content.columnconfigure(0, weight=1)
content.columnconfigure(1, weight=1)
content.columnconfigure(2, weight=1)
content.columnconfigure(3, weight=1)

# This doesn't work - screen hasn't been rendered yet
print("pre-init bbox ", content.bbox())

root.mainloop()
Community
  • 1
  • 1
Dave
  • 3,834
  • 2
  • 29
  • 44

1 Answers1

2

The methods winfo_width and winfo_height will give you the actual size of a given widget.

Note that neither these methods, nor bbox, will give you anything useful until the widgets are actually rendered to the screen. If you need to use them you will need to make sure the event loop has had a chance to update the display.

Also, be aware that the bbox method returns the bounding box of the slave widgets inside the widget, not the bounding of of the widget itself. That is why the results for frame.grid_bbox() return all zeros -- it has nothing inside it so the bounding box is 0,0,0,0. You should, however, see numbers for content.box() once the display has been rendered. On my box, for instance, I get (0, 0, 352, 125)

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Thanks - my real app has timer-based updates, and bbox() returns zeros both during initialization and after the event loop is running. I'll add a resize callback to the toy code because I still want to figure out how bbox() is supposed to work. – Dave Aug 22 '12 at 13:52
  • @Dave: Are you _certain_ that bbox is returning all zeros in all cases? I see it returning valid numbers for `content.bbox()` once the display has been updated. I've updated my answer to explain why `frame.grid_bbox()` always returns (0,0,0,0). – Bryan Oakley Aug 22 '12 at 14:20
  • I was surprised to see the resize callback returning the correct size for the toy code. And the embarassing truth is that I added bbox to a reset button callback in my app, but I also call that routine to set things up before the screen is rendered. Thanks for the help - I won't delete the question yet in case others can benefit from my carelessness. – Dave Aug 22 '12 at 15:24