Stephen D
Stephen D

Reputation: 3076

TKinter, place widgets on certain parts of the window aligning with the background image

I would like to have my buttons and text neatly placed within the confines of the "Login" box area. The "Login" box is actually part of the background PNG image that I load with TKinter. I would like to get my widgets placed nicely within that Login box in the background. I am currently using grid(), but for some reason they are not aligning with that Login box. How can I adjust my code to get things inside of the Login box?

def build_login_screen(root):
    background_image = PhotoImage(file="./loginScreen.png", name="background_image")
    background_label = Label(root, image=background_image, name="background_label")
    background_label.place(x=0, y=0, relwidth=1, relheight=1)
    background_label.image = background_image
    login_button = Button(root, text="Login", name="login_button", command=lambda: login(root))
    login_button.grid(row=5, column=1)
    quit_button = Button(root, text="Quit", name="quit_button", command=root.destroy)
    quit_button.grid(row=8, column=1)
    server_select = Combobox(root, name='server_select')
    server_select['values'] = (remote_server, local_server)
    server_select.current(0)  
    server_select.grid(row=4, column=1)
    server_select.bind("<<ComboboxSelected>>", clickServer)
    label_server_status = Label(root, padx=50, text="Checking server status..", name="label_server_status")
    label_server_status.grid(row=4, column=2)
    label_server_status_value = Label(root, padx=50, text=server_availability, name="label_server_status_value")
    label_server_status_value.grid(row=4, column=3)

tkinter window

Upvotes: 0

Views: 231

Answers (3)

Somraj Chowdhury
Somraj Chowdhury

Reputation: 1043

You can neatly place all your widgets using the grid geometry manager. Also you must consider providing some padding using the following options padx, pady, ipadx & ipady to make your GUI look neat and aligned.

I have commented some lines of your code as they were probably defined in some other section of the code which you didn't include in your question.

So basically the changes I made were that I used only the grid system. Set the label background_label inside your root window, and then arranged all the other widgets inside of the background_label so that there is a hierarchy

root (contains) background_label (contains) Buttons, labels and other widgets

And finally gave some padding to each of the widgets.

Code:

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

root = tk.Tk()

background_image = ImageTk.PhotoImage(file="./img/bg.jpg", name="background_image")
background_label = tk.Label(root, image=background_image, name="background_label", height=200, width=160)
background_label.grid(row=0, column=0, pady=10, padx=10, ipady=10, ipadx=3)
background_label.image = background_image

login_button = tk.Button(background_label, text="Login", name="login_button", command=lambda: login(root))
login_button.grid(row=1, columnspan=3, pady=(4,8))

quit_button = tk.Button(background_label, text="Quit", name="quit_button", command=root.destroy)
quit_button.grid(row=2, columnspan=3)

server_select = ttk.Combobox(background_label, name='server_select')
#server_select['values'] = (remote_server, local_server)
#server_select.current(0)  
server_select.grid(row=0, column=0, pady=4, padx=(6,5))
#server_select.bind("<<ComboboxSelected>>", clickServer)

label_server_status = tk.Label(background_label, padx=50, text="Checking server status..", name="label_server_status")
label_server_status.grid(row=0, column=1, pady=4, padx=(0,5))

label_server_status_value = tk.Label(background_label, padx=50, text='server_availability', name="label_server_status_value")
label_server_status_value.grid(row=0, column=2, pady=4, padx=(0,5))

root.mainloop()

Output: This is what the GUI looks when you run the above code

background image with widgets

You can play around with the padding options and set them to your requirements. Hope you understood my explanation.

Upvotes: 1

Paul Cornelius
Paul Cornelius

Reputation: 10906

My suggestion is to create a frame with a transparent background. You the place this frame (using the place layout manager) so that it is positioned exactly over the rectangle in the center. Then you can add the buttons to the transparent frame using standard layout managers. This arrangement would be more flexible and easier to understand.

Widgets with transparent backgrounds are supported in TkInter versions >8.6, which is probably what you have unless your Python installation is very old. For more information see: Is there a way to create transparent windows with Tkinter?

Upvotes: 2

sciroccorics
sciroccorics

Reputation: 2427

As your interface includes an image with a fixed size, the easiest solution would be to define the position of your Buttons with the place geometry manager (instead of the grid manager), as you already did to locate your image. Simply find coordinates by trial-and-error, until you get something visually pleasing.

You may still use grid for the other widgets...

Upvotes: 2

Related Questions