Search code examples
pythontkintergrid-layout

Why does the 'ipady' option in the tkinter.grid() method only add space below a widget?


Below is a code to show the issue. Label1 shows that I need to use pady to displace Label1 by 10 pixels. Label2 shows the default effect of ipady. Why does ipady not leave space above and below the widgets? How do I get ipady to do what it is suppose to do w/o using pady? Thank you.

Quoting tcl documentation:

-ipady amount

The amount specifies how much vertical internal padding to leave on the top and bottom of the slave(s). This space is added inside the slave(s) border. The amount defaults to 0.

import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()

s = ttk.Style()
s.configure('one.TFrame', background='light blue', relief='raised',borderwidth=10)
s.configure('two.TFrame', background='light green', relief='sunken', borderwidth=10)

frame1 = ttk.Frame(root,style='one.TFrame')
frame1.grid(row=0, column=0, sticky='nsew', ipady=10,)

label1 = ttk.Label(frame1, text='Label1')
label1.grid(sticky='nsew',padx=10, pady=10,)

frame2 = ttk.Frame(frame1,style='two.TFrame')
frame2.grid(row=1, column=1, sticky='nsew', ipady=50,)

label2 = ttk.Label(frame2, text='Label2')
label2.grid()

Solution

  • I don't think ipady quite does what you think it does. Admittedly, the documentation is a bit unclear on this point. It doesn't add the equivalent of an interior margin. Instead, it simply adds that many pixels to the height of the widget, and the pixels are added on the inside of the border rather than the outside. It doesn't "block off" these pixels from being used.

    If your frame normally would be 20 pixels tall, with ipady=50, your widget will now be 120 pixels tall (50*2 + 20). Any widgets added inside of this frame are able to use all of the space inside the frame. Thus, when you use grid to place something in row zero, it will still appear at the very top of the frame, just below the border.

    This is exactly what I see with your code. On my machine, frame2 without ipady=50 ends up being 20 pixels tall. When I add ipady=50, the frame becomes 120 pixels tall. The label appears at the very top of the frame since it has been placed in row zero.

    TL;DR: don't think of ipady as saying "I need this much of an inside margin", but rather "I need this much more extra space inside".