Skip to content
Advertisement

How to make tkinter’s GUI components dynamic?

I am making a tkinter application for Windows, and I want to make the widget placements dynamic. Like in this picture, the Label (which is acting like a background image holder), is covering the Y-axis, but when I maximize the window, like here, the photo does not cover the whole Y-axis.

How to fix this, or is there a way to disable the windows’ maximize button, without using root.overridedirect()?

Here is the code →

#importing everything
from tkinter import *
from pypresence import Presence
import time


#making the root window
root = Tk()

dimension = (
    800,
    500
)
#setting the window
bg = PhotoImage(file = r'C:UsersHunterDesktopschool 1modulepbmbg.png')
background = Label(root, bd=0, image=bg)
background.place(x=0, y=0, relwidth=1, relheight=1)

root.geometry(f'{dimension[0]}x{dimension[1]}')


#main thing
root.mainloop()

Advertisement

Answer

You can do what you want by binding an event-handling function so it will be called whenever a root window <Configure> event occurs. This will allow you to change the size of the image attached the Label whenever the root window is moved or resized.

In the code below, the Pillow fork of the PIL (Python Imaging Library) is used to do the image resizing since tkinter doesn’t provide a native way of doing it. The original image is stored separately and all scaling that needs to be done placing it on the Label is always relative to its size. This prevents errors from accumulating and degrading the image displayed.

Note I also changed your from tkinter import * to import tkinter as tk because there was a conflict between a tkinter.Image and a PIL.Image. It’s generally best to avoid import * prevent this from happening anyway.

from PIL import Image, ImageTk
import tkinter as tk
import time


DIMENSION = 800, 500

def config_callback(event):
    global bg
    window_w, window_h = root.winfo_width(), root.winfo_height()

    # New height of image is original height * ratio of current to starting size of window.
    new_height = round(orig_height * (window_h/DIMENSION[1]))
    # Resize original image to this new size (without changing width).
    bg = ImageTk.PhotoImage(orig_img.resize((orig_width, new_height), Image.ANTIALIAS))
    background.config(image=bg)

root = tk.Tk()

#image_path = r'C:UsersHunterDesktopschool 1modulepbmbg.png'
image_path = r'.bkgr.png'

orig_img = Image.open(image_path)
orig_width, orig_height = orig_img.size
bg = ImageTk.PhotoImage(orig_img.resize((orig_width, orig_height), Image.ANTIALIAS))

background = tk.Label(root, bd=0, image=bg)
background.place(x=0, y=0, relwidth=1, relheight=1)

root.geometry(f'{DIMENSION[0]}x{DIMENSION[1]}')
root.bind('<Configure>', config_callback) # Callback on window move/resize

root.mainloop()

Here’s a screenshot showing what it looks like originally:

initial screenshot

Here’s another showing what it looked like after changing the window’s height:

screenshot after changing window height

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement