Tkinter background with overlapping buttons? - python

I have made a scoreboard and i want to add a background to it. If i dont use the background image, my buttons will display but when im using the background image my buttons are 'disappearing'. This is a little piece of my code, how can i place the button in front of the background?. Thanks for helping me.
from tkinter import *
player1health = 100
player2health = 100
player3health = 100
player4health = 100
class Window(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title("Scoreboard")
self.pack(fill=BOTH, expand = 1)
# Background
image1 = PhotoImage(file="C:/Users/Ahmet/OneDrive/Desktop/SC/achtergrond1.png")
w = image1.width()
h = image1.height()
root.geometry("600x500")
panel1 = Label(root, image=image1)
panel1.pack(side='top', fill='both', expand='yes')
panel1.image = image1
#Player1
self.Name1 = Label(root, text = input("Name player 1: "), font=("Helvetica", 16))
self.Name1.place(x=80,y=50)
#scoretracker
self.Score1 = Label(root,text= 'Score:' )
self.Score1.place(x=55, y=80)
self.L1 = Label(root,text= player1health )
self.L1.place(x=100, y=80)
self.HP1 = Label(root,text= 'HP' )
self.HP1.place(x=125, y=80)
self.add = Label(root, text = "Add",font=("Helvetica", 13))
self.add.place(x = 30,y=120)
#button
player_1_add_10_Button = Button(self, text = "10 HP",)
player_1_add_10_Button.place(x=30,y=140)
player_1_add_20_Button = Button(self, text = "20 HP",)
player_1_add_20_Button.place(x=30,y=170)
player_1_add_30_Button = Button(self, text = "30 HP",)
player_1_add_30_Button.place(x=30,y=200)
root = Tk()
root.geometry("600x500")
root.configure(background="light blue")
Label(root, text='Scoreboard:', bg= 'light blue').pack()
app = Window(root)
root.mainloop()

The label containing the background image is a slave of root. So are the labels you create in the init_window() function, but the buttons are slaves to self.
So, instead of:
panel1 = Label(root, image=image1)
try
panel1 = Label(self, image=image1)
And do the same change for all the buttons as well. That should work better.

Related

How to expand buttons and labels to fill the x axis in python tkinter?

This is a part of code from my school project.
from tkinter import *
from tkinter.font import Font
class student_window():
def __init__(self, master):
self.student_win = master
#window = Toplevel(self.master)
self.student_win.geometry("1280x720")
self.header1Font = Font(family='Helvetica', size=20)
self.optionFont = Font(family='Sans Serrif', size=20)
self.student_win.focus()
self.show_window()
def show_window(self):
print("ookk")
self.student_win.title("Student Window")
self.option_frame = Frame(self.student_win, width=200, height=720)
lbl_header = Label(self.option_frame,text="EXAMINATION", font=self.header1Font, fg='white', bg='#172D44').grid(row=0,column=0, sticky=NSEW)
lbl_welcome = Label(self.option_frame, text="Welcome,", fg='#E9F1F7', bg='#2A3F54').grid(row=1,column=0)
lbl_username = Label(self.option_frame, text="Username", fg='white', bg='#2A3F54').grid(row=2,column=0)
lbl_header2 = Label(self.option_frame, text="STUDENT CORNER", fg='white', bg='#2A3F54').grid(row=3, column=0)
self.btn_tests = Button(self.option_frame, text="Attempt Exam", fg='#E9F1F7', bg='#35495D', relief=FLAT)
self.btn_tests.grid(row=4,column=0, sticky=NSEW)
self.btn_attempts = Button(self.option_frame, text="Attempts", fg='#E9F1F7', bg='#2A3F54', relief=FLAT)
self.btn_attempts.grid(row=5, column=0, sticky=NSEW)
self.btn_result = Button(self.option_frame, text="Result", fg='#E9F1F7', bg='#2A3F54', relief=FLAT)
self.btn_result.grid(row=6, column=0, sticky=NSEW)
self.btn_goBack = Button(self.option_frame, text="Go Back", fg='#E9F1F7', bg='#2A3F54', relief=FLAT)
self.btn_goBack.grid(row=7, column=0, sticky=NSEW)
self.option_frame.configure(bg='#2A3F54')
self.option_frame.grid(row=0, column=0)
self.option_frame.grid_propagate(0)
self.main_frame = Frame(self.student_win, width=880, height=720)
self.main_result_frame = Frame(self.main_frame)
self.main_result_frame.grid(row=0,column=0)
self.attempts_frame = Frame(self.main_frame)
self.attempts_frame.grid(row=0, column=0)
self.test_frame = Frame(self.main_frame)
lbl_test = Label(self.test_frame, text="In test frame").pack()
self.test_frame.grid(row=0,column=0)
self.main_frame.grid(row=0,column=1)
self.main_frame.grid_propagate(0)
self.info_frame = Frame(self.student_win, width=200, height=720)
self.btn_username = Button(self.info_frame, text="Username", relief=FLAT)
self.btn_username.grid(row=0,column=0)
self.userInfo_frame = Frame(self.info_frame)
self.info_frame.grid(row=0, column=2)
self.info_frame.grid_propagate(0)
root = Tk()
student_window(root)
root.mainloop()
And it looks something like this.
The Student Panel for my project
The whole window is divided into three frames and want to expand each label and button of the left frame(self.option_frame) to fill it horizontally. I tried doing sticky=EW and sticky=NSEW but still some space is left. How do I fix that?
You need to call self.option_frame.columnconfigure(0, weight=1) to make column 0 to use all the available horizontal space.
I was just trying some things and what I have found to be working is to make the label width bigger than than the frame then anchoring the text to the left.

How to make button using canvas in toplevel() Tkinter

I'm trying to make a button using canvas.create_window in toplevel() in Tkinter. Button is used to go back to main window. First "Start" button is displayed but second "Back" button is not. Code below.
from tkinter import *
win = Tk()
def play_button():
win.withdraw()
top = Toplevel()
top.geometry("300x300")
button_back = Button(top, text="Back", command=back_button)
canvas_two = Canvas(top, width = 300, height = 300)
canvas_two.pack(fill="both", expand=True)
Button_reverse = canvas_two.create_window(0, 0, anchor="nw", window=button_back)
top.resizable(False, False)
def back_button():
win.deiconify()
win.geometry("300x300")
canvas = Canvas(win, width = 300, height = 300)
canvas.pack(fill="both", expand=True)
button_play = Button(win, text="Play", command=play_button)
Play_button = canvas.create_window(0, 0, anchor="nw", window=button_play )
win.mainloop()
The problem is the ordering of creation of canvas_two and button_back. You need to create the Canvas first and then put the Button on top of it as shown below.
def play_button():
win.withdraw()
top = Toplevel()
top.geometry("300x300")
canvas_two = Canvas(top, width=300, height=300)
canvas_two.pack(fill="both", expand=True)
button_back = Button(top, text="Back", command=back_button)
Button_reverse = canvas_two.create_window(0, 0, anchor="nw", window=button_back)
top.resizable(False, False)

How to use 2nd Tkinter window to change image in 1st?

Quick summary: The green button is supposed to change when an image is selected, but it doesn't:
I have a Tkinter window-A with a button that when pressed will use a separate Python file to create a new window-B. Window-B has two buttons: new screen-snip or select image from folder. The method used for this is supposed to then change self.image_selected so that it can be used to update the button in window-A to have this new image.
I've tried both lines of code below, and neither are working. I'm not getting any errors either:
self.button.configure(image = img.image_selected) # first try
self.button['image'] = img.image_selected # second try
Here is my code (simplified for clarity):
import tkinter as tk
import get_image_or_snip
class ButtonImg:
def __init__(self, master):
self.newWindow = None
self.master = master
self.title = "My Minimum Reproducible Example"
self.fontA = ("arial", 20, "bold")
self.canvas = tk.Canvas(height = 5)
self.canvas.pack()
self.button = tk.Button(bg="#93d9cc", height = 5, text = "Select Image",
font = self.fontA, command = self.changeImage)
self.button.pack(fill="both")
def changeImage(self):
self.newWindow = tk.Toplevel(self.master)
img = get_image_or_snip.AcquireImage(self.newWindow)
self.button.configure(image = img.image_selected)
#self.button['image'] = img.image_selected
root = tk.Tk()
app = ButtonImg(root)
root.mainloop()
Here is the aforementioned get_image_or_snip.py code:
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk, Image
import snipping_tool
class AcquireImage:
def __init__(self, master):
self.master = master
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command =lambda: self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command=lambda: self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")
self.image_selected = None
self.master.mainloop()
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename()
load_img = Image.open(ret)
self.image_selected = ImageTk.PhotoImage(load_img)
if method == 2:
ret = snipping_tool.get_snip()
self.image_selected = ret
def main():
root = tk.Tk()
AcquireImage(root)
root.mainloop()
if __name__ == '__main__':
main()
If you add print() before and after get_image_or_snip.AcquireImage(self.newWindow) in changeImage() then you should see only first text because you run second mainloop() and it never ends this loop and never go back to changeImage() and never runs self.button.configure(image=img.image_selected)
You should use only one mainloop() and eventually use
root.wait_window(self.newWindow)
to wait until you close second window and then it will run self.button.configure(image=img.image_selected)
But there are other problems.
It removes image from memory memory when second windows is destroyed so you have to assign it to variable in first window.
Button use height in chars when you sent text but when you assign image then it use height in pixels and you have to change it from 5 to image.height()`
All code in one file
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk
class AcquireImage:
def __init__(self, master):
self.master = master
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")
self.image_selected = None
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename(initialdir='/home/user/images/')
if ret:
self.image_selected = ImageTk.PhotoImage(file=ret)
self.master.destroy()
elif method == 2:
self.image_selected = snipping_tool.get_snip()
class ButtonImg:
def __init__(self, master):
self.newWindow = None
self.master = master
self.title = "My Minimum Reproducible Example"
self.fontA = ("arial", 20, "bold")
self.canvas = tk.Canvas(height=5)
self.canvas.pack()
self.button = tk.Button(bg="#93d9cc", height=5, text="Select Image",
font=self.fontA, command=self.changeImage)
self.button.pack(fill="both")
def changeImage(self):
print('open second window')
self.newWindow = tk.Toplevel(self.master)
img = AcquireImage(self.newWindow)
self.master.wait_window(self.newWindow)
print('close second window')
if img.image_selected: # check if image was selected
self.image = img.image_selected
self.button.configure(image=self.image, height=self.image.height())
root = tk.Tk()
app = ButtonImg(root)
root.mainloop()
BTW: If you want to change image without closing second window then you should send first window (or button from first window) as argument to second window and change image in show_dialogs()
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk
class AcquireImage:
def __init__(self, master, first_window):
self.master = master
self.first_window = first_window
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")
self.image_selected = None
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename(initialdir='/home/user/images/')
if ret:
self.image_selected = ImageTk.PhotoImage(file=ret)
self.first_window.image = self.image_selected
self.first_window.button.configure(image=self.first_window.image, height=self.first_window.image.height())
elif method == 2:
self.image_selected = snipping_tool.get_snip()
class ButtonImg:
def __init__(self, master):
self.newWindow = None
self.master = master
self.title = "My Minimum Reproducible Example"
self.fontA = ("arial", 20, "bold")
self.canvas = tk.Canvas(height=5)
self.canvas.pack()
self.button = tk.Button(bg="#93d9cc", height=5, text="Select Image",
font=self.fontA, command=self.changeImage)
self.button.pack(fill="both")
def changeImage(self):
self.newWindow = tk.Toplevel(self.master)
img = AcquireImage(self.newWindow, self) # first window as `self` but you can send `self.button`
root = tk.Tk()
app = ButtonImg(root)
root.mainloop()
EDIT: Doc about creating Dialog Windows

How do I make a table that updates from user input in the box before with tkinter?

The overall aim of the program is to make a scoreboard that displays the scores of both teams and individuals. It needs to contain 4 columns and 5 rows for the team aspect and 20 separate spaces for individual inputs.
I want to make a table that uses user input using the previous box that I had created. So far, I have created up to the point where the user needs to input their team name and displays a table with no entries. I need it to display the events that they are doing as well as the score and their team name/name.
I am new to Python and tkinter so anyone who can help me solve this problem would be great!
from tkinter import *
import tkinter as tk
from time import sleep
def team_name():
print('Okay, what is your team name?')
window = Toplevel(main)
thirdLabel = Label(window, text='Please enter your team name below:',
bg='black', fg='yellow')
thirdLabel.pack()
Label2 = Label(window,text = '')
Label2.pack(padx=15,pady= 5)
entry2 = Entry(window,bd =5)
entry2.pack(padx=15, pady=5)
buttonconfirm1 = Button(window, text='Confirm',command=confirm1)
buttonconfirm1.pack()
def confirm1 ():
window = Toplevel(main)
confirmLabel = Label(window, text='Scoreboard', bg='black',
fg='yellow')
confirmLabel.pack(fill=X)
def table ():
window = Toplevel(main)
label3 = Label(window, text='Team name/Individual name', bg='black',
fg='yellow')
label3.pack()
firstBox = Entry(window, bd=1)
firstBox.pack()
secondBox = Entry(window, bd=1)
secondBox.pack()
thirdBox = Entry(window, bd=1)
thirdBox.pack()
def scoreboard():
window = Toplevel(main)
entry_1 = Label(window, text = '')
entry_2 = Label(window, text = '')
def individual_name():
print('Okay, what is you name?')
window = Toplevel(main)
secondLabel = Label(window, text='Please enter your name below',
bg='black', fg='yellow')
secondLabel.pack()
Label1 = Label(window,text = '')
Label1.pack(padx=15,pady= 5)
entry1 = Entry(window,bd =5)
entry1.pack(padx=15, pady=5)
buttonConfirm = Button(window, text='Confirm', command=table)
buttonConfirm.pack()
def confirm ():
window = Toplevel(main)
confirmLabel = Label(window, text='Scoreboard', bg='black', fg='yellow')
confirmLabel.pack(fill=X)
def close():
main.destroy()
main = Tk()
main.maxsize(800,600)
# Labels section
main_menu_label = Label(main, text='Welcome to the scoreboard! Please
select from the options below:', bg='Black',
fg='white')
# Using a photo for top frame on menu and making a label to place it
photo = PhotoImage(file='Scoreboard.gif')
photo_label = Label(main, image=photo)
photo_label.pack(side=TOP)
# Invisible frames for widget placement
top_frame = Frame(main)
top_frame.pack()
bottom_frame = Frame(main)
bottom_frame.pack(side=BOTTOM)
print('Okay! What is your team name?')
# Buttons for main menu and display on the screen
first_button = Button(top_frame, text='Are you entering as an
individual?', fg='yellow', bg='black',
command=individual_name)
second_button = Button(bottom_frame, text='Are you entering as a team?',
fg='yellow', bg='black', command=team_name)
quit_button = Button(bottom_frame, text='Quit?', fg='yellow', bg='black',
command=close)
first_button.pack()
second_button.pack()
quit_button.pack()
main.mainloop()
Sorry if this is a bit confusing, I can't really explain much more than I already have!

Python 3.6 - Resizing Tkinter Buttons In Accordance With Frame Size

I have been looking around on stack overflow for ages trying to find the answer to this but I just can't get anything to work, therefore I am asking this question. I have a little program with three buttons and a label, and they are in a grid. I was wondering how no matter the size or shape the buttons and label would stay the same relative to the frame. Similar to if I resized an image, everything stays the same size.
Here is my code:
from tkinter import *
class Window(Frame): #All the stuff for the GUI
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.init_window()
self.grid()
def init_window(self):
self.master.title("EncryptDecrypt")
self.pack(fill = BOTH, expand = 1)
quitButton = Button(self, text = "Quit", command = self.client_exit, width = 10, height = 5) #Quit Button
quitButton.grid(row = 0, column = 0, sticky = W)
encryptModeButton = Button(self, text = "Encrypt", command = lambda: self.execute("decrypted.txt", "encrypted.txt", 1, 0), width = 10, height = 5) #Encrypt Button
encryptModeButton.grid(row = 0, column = 1, sticky = W)
decryptModeButton = Button(self, text = "Decrypt", command = lambda: self.execute("encrypted.txt", "decrypted.txt", 0, 1), width = 10, height = 5) #Decrypt button
decryptModeButton.grid(row = 0, column = 2, sticky = W)
myLabel = Label(self, text = "Select The Action You Wish To Undertake", font = ("Purisa", 15))
myLabel.grid(row = 0, column = 3)
root = Tk()
root.geometry("610x80")
app = Window(root)
root.mainloop()
Sorry if the answer is obvious, I have already tried pack()
There's a good tutorial to grid packer. Just scroll over "Handling Resize" and you would notice how to use sticky option and configure weight of column/row pair.
So let's try your example with grid packer:
from tkinter import *
class Window(Frame): #All the stuff for the GUI
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.master.minsize(width=650, height=80)
self.configure(relief=RAISED, borderwidth=10)
self.init_window()
self.grid(sticky = NSEW)
def init_window(self):
self.master.title("EncryptDecrypt")
# configure weights; note: that action need for each container!
self.master.rowconfigure(0, weight=1)
self.master.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
for i in range(4):
self.columnconfigure(i, weight=1)
quitButton = Button(self, text = "Quit", width = 10, height = 5) #Quit Button
quitButton.grid(row = 0, column = 0, sticky = NSEW)
encryptModeButton = Button(self, text = "Encrypt", width = 10, height = 5) #Encrypt Button
encryptModeButton.grid(row = 0, column = 1, sticky = NSEW)
decryptModeButton = Button(self, text = "Decrypt", width = 10, height = 5) #Decrypt button
decryptModeButton.grid(row = 0, column = 2, sticky = NSEW)
myLabel = Label(self, text = "Select The Action You Wish To Undertake", font = ("Purisa", 15))
myLabel.grid(row = 0, column = 3, sticky = NSEW)
root = Tk()
root.geometry("650x80")
app = Window(root)
root.mainloop()
As you see - I just added a sticky=NSEW and columnconfigure/rowconfigure and seems like it works like you wish!
The weak side of this is the need to configure each container!
But here, in pack manager, there're more intuitive and performing the same role options - fill and expand!
from tkinter import *
class Window(Frame): #All the stuff for the GUI
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.master.minsize(width=650, height=80)
self.configure(relief=RAISED, borderwidth=10)
self.init_window()
self.pack(fill=BOTH, expand=True)
def init_window(self):
self.master.title("EncryptDecrypt")
quitButton = Button(self, text = "Quit", width = 10, height = 5) #Quit Button
quitButton.pack(fill=BOTH, side=LEFT, expand=True)
encryptModeButton = Button(self, text = "Encrypt", width = 10, height = 5) #Encrypt Button
encryptModeButton.pack(fill=BOTH, side=LEFT, expand=True)
decryptModeButton = Button(self, text = "Decrypt", width = 10, height = 5) #Decrypt button
decryptModeButton.pack(fill=BOTH, side=LEFT, expand=True)
myLabel = Label(self, text = "Select The Action You Wish To Undertake", font = ("Purisa", 15))
myLabel.pack(fill=BOTH, side=LEFT, expand=True)
root = Tk()
root.geometry("650x80")
app = Window(root)
root.mainloop()
What to use is your choice!
And there're a good topic about resizing, grid and pack! Take a look
Some other useful links:
Tkinter Geometry Managers
Grid Geometry Manager
grid columnconfigure
grid rowconfigure

Categories