pythontkinter

Is there a way for empty tkinter frame objects to take up space?


I have an app which you can upload a picture into an image label object, but until I uploaded the picture, the image label just didn't take up space. So I put the image in a frame, but it still didn't take up space until I uploaded the image. Is there any way around this?

Here is my code:

from tkinter import filedialog
from tkinter import *
from PIL import Image, ImageTk

####################### FUNCTIONS ################################

def upload_image():

    file_path = filedialog.askopenfilename()

    if file_path:
        img = Image.open(file_path)

        img_tk = ImageTk.PhotoImage(img)

        image_label.image = img_tk
        image_label.config(image=img_tk)
        


##################### GUI ##################################

window = Tk()

img_frame = Frame(window, width=500, height=500)
image_label = Label(img_frame)

upload_button = Button(window, text='Upload Image', command=upload_image)

# Other UI things...



img_frame.grid(column=3, row=2, columnspan=5, rowspan=10, padx=50)
image_label.pack()
upload_button.grid(column=1,row=1, padx=60, pady=60)


window.mainloop()

Edit: I have many more elements too

text_size_label = Label(window, text="Text size:", font=('calibre',12, 'bold'))
text_size = ttk.Combobox(window, font=('calibre',12, 'normal'), values=list(np.arange(8, 51, step=7)))

rotation_label = Label(window, text="Rotation:", font=('calibre',12, 'bold'))
rotation = Entry(window, font=('calibre',12, 'normal'))

opacity_label = Label(window, text="Opacity:", font=('calibre',12, 'bold'))
opacity = Scale(window, from_=0, to=100, orient='horizontal')

text_label = Label(window, text='Text:', font=('calibre',12, 'bold'))
text = Entry(window, font=('calibre',12, 'normal'))

font_label = Label(window, text='Font:', font=('calibre', 12, 'bold'))
font = Entry(window, font=('calibre',12, 'normal'))

lines_label = Label(window, text='Lines:', font=('calibre', 12, 'bold'))
lines = Entry(window, font=('calibre', 12, 'normal'))

per_line_label = Label(window, text='Watermarks per Line:', font=('calibre', 12, 'bold'))
per_line = Entry(window, font=('calibre', 12, 'normal'))

# Placements 
img_frame.grid(column=3, row=2, columnspan=5, rowspan=10, padx=50)
image_label.pack()
upload_button.grid(column=1,row=1, padx=60, pady=60)
text_size_label.grid(column=1, row=2)
text_size.grid(row=2, column=2)
rotation_label.grid(row=3, column=1)
rotation.grid(row=3, column=2)
opacity_label.grid(row=4, column=1)
opacity.grid(row=4, column=2)
text_label.grid(row=5, column=1)
text.grid(row=5, column=2)
font_label.grid(row=6, column=1)
font.grid(row=6, column=2)
lines_label.grid(row=7, column=1)
lines.grid(row=7, column=2)
per_line_label.grid(row=8, column=1)
per_line.grid(row=8, column=2)

Solution

  • Assign an image to the label from start (not just when you have an actual image). Then, width and height attribute of the label will do what you expect them to

    
    img_frame = Frame(window) # not really needed width=500, height=500)
    image_label = Label(img_frame, image=PhotoImage(), width=500, height=500)