How do I link a widget to a function in Tkinter [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
This is my current code. I am looking to link the buttons I made to open a new window. I want the old Window to then close. When the new Window opens, how do I go about creating a new interface for that Window.
Code:
import tkinter as tk
HEIGHT = 950
WIDTH = 650
root=tk.Tk()
canvas = tk.Canvas(root, height=HEIGHT, width=WIDTH)
canvas.pack()
frame = tk.Frame(root, bg='#80c1ff')
frame.place(relx=0.5, rely=0.1, relwidth=0.75, relheight=0.1, anchor='n')
button = tk.Button(frame, text="Credit Score Checker")
font = ("Helvetica",20,"bold")
button.place(relx=-0, relheight=1, relwidth=0.27)
button = tk.Button(frame, text="Financial Advisor")
font = ("Helvetica",20,"bold")
button.place(relx=0.25, relheight=1, relwidth=0.27)
button = tk.Button(frame, text="Insurance Planner")
font = ("Helvetica",20,"bold")
button.place(relx=0.5, relheight=1, relwidth=0.27)
button = tk.Button(frame, text="Goal Setter")
font = ("Helvetica",20,"bold")
button.place(relx=0.75, relheight=1, relwidth=0.26)
lower_frame = tk.Frame(root, bg='#80c1ff', bd=10)
lower_frame.place(relx=0.5, rely=0.25, relwidth=0.75, relheight=0.6, anchor='n')
label = tk.Label(lower_frame, text="Summary of finances", bg='grey')
label.place(relx=0.5, rely=0, anchor='n', relwidth=0.9, relheight=1)
root.mainloop()

Here is an example of a button that opens up a new window when clicked I hope this helps
from tkinter import *
main = Tk()
main.geometry("1000x1000")
main.title("Welcome")
canvas = Canvas(main, width = 1500, height = 1000, bg = "spring green")
canvas.place(relx = 0.5, rely = 0.5, anchor = CENTER)
frame = Frame(main)
frame = Frame(main, width = 500, height = 500, bg = "cyan")
frame.place(relx = 0.5, rely = 0.5, anchor = CENTER)
frame3 = Frame(main, width=300, height=300, bg="orange")
frame3.place(relx = 0.5, rely = 0.5, anchor = CENTER)
# LABEL:
lbl = Label(main, text = "Hi", fg = "deep pink", font = ("Fixedsys",30), bg = "spring green")
lbl.place(relx = 0.5, rely = 0.5, anchor = CENTER)
# FUNCTION FOR BUTTON:
def on_click():
root = Tk()
frame2 = Frame(root)
frame2 = Frame(root, width = 1000, height = 1000, bg = "cyan")
frame2.place(relx = 0.5, rely = 0.5, anchor = CENTER)
root.geometry("700x700")
root.title("SUP")
label_new = Label(root, text = "There you go :)", font = ("Fixedsys", 22), fg = "red", bg = "black")
label_new.place(relx = 0.5, rely = 0.5, anchor = CENTER)
# BUTTON:
btn = Button(main, text = "this is a button", fg = "blue", font = ("Fixedsys",20), bg = "dark turquoise", command=on_click)
btn.place(relx = 1.0, rely = 0.0, anchor = NE)
main.mainloop()

If you really want to create a new window every time the button is pressed and display the new widgets on this window, then the other answers provide an excellent solution. But rather than create a new window to display the new widgets, I would recommend simply destroying the old widgets on the current window and putting up the new ones on the same window. It has the same effect as "closing the old window and creating a new one".
To destroy all the widgets on the screen, simply write a function like this and call it whenever you want to remove all the old widgets and put up new ones.
def clear() :
for widget in root.winfo_children() :
widget.destroy()
The above function iterates through all the widgets that have been put up on the window and destroys them, one by one.
Here is an example code to illustrate how this works.
import tkinter as tk
root = tk.Tk()
root.config(bg="#424242")
def clear() :
for widget in root.winfo_children() :
widget.destroy()
def window1() :
clear()
lbl1 = tk.Label(root,text="Hey there! Im part of window1!!",fg="white",bg="#424242")
lbl1.pack()
lbl2 = tk.Label(root,text="Im also a part of window1!!",fg="white",bg="#424242")
lbl2.pack()
btn1 = tk.Button(root,text="Press me to display window2",command=window2,fg="white",bg="#424242")
btn1.pack()
def window2() :
clear()
lbl1 = tk.Label(root,text="Hey there! Im part of window2!!",fg="white",bg="#424242")
lbl1.pack()
lbl2 = tk.Label(root,text="Im also a part of window2!!",fg="white",bg="#424242")
lbl2.pack()
btn1 = tk.Button(root,text="Press me to display window1",command=window1,fg="white",bg="#424242")
btn1.pack()
window1()
root.mainloop()
Here, as Cool Cloud has already said, a command parameter is passed to the button with the next function to be called. Both the functions,window1 and window2 call the clear function first which effectively clears the screen ,and then the new widgets are put up on the window.

Related

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)

Tkinter building windows similar to Root

I am currently working on Tkinter codes. I happen to need to create new windows exactly similar to root but my codes do not perfectly work well. The title does not appear on the new windows. This is an excerpt:
from tkinter import *
#New Window
def New_page():
window()
#Main Window
def window():
window = Tk()
window.resizable(0,0)
window.configure(background='grey')
window.state('zoomed')
window.geometry("2000x4000")
#Title Frame
TITLE_FRAME = Frame(window, relief = GROOVE, bg = "black", width=2000, height=160).grid(row=0, column=0, columnspan = 150, rowspan = 30, sticky=E+W)
Label(TITLE_FRAME, text= 'THIS IS THE TITLE PART', fg='sky blue', bg='black', font='none 40 bold',
borderwidth=5).grid(row=0,column=10)
#New Window Button
ENTRY_FRAME = Frame(window, bg='sky blue', relief = SUNKEN)
ENTRY_FRAME.grid(row=40, column=0, columnspan=20, padx=15, pady=15)
Label(ENTRY_FRAME, text= 'SELECT THE APPROPRIATE DETAILS:',
bg = 'sky blue', fg='black', font='none 10 bold', borderwidth=5).grid(row=0, column=0, columnspan=20)
NEW_WINDOW = Button(ENTRY_FRAME, text="NEW WINDOW", font='None 8 bold', width=30, command=New_page, fg= 'black', bg='white')
NEW_WINDOW.grid(row = 3, column = 0, columnspan = 3, padx = 10, pady = 10)
window.mainloop()
#Calling the Tkinter function
window()
Like in the comments, Toplevel is the way to go for this one. What I changed:
Moved making the window object globally
Renamed the function to make it makeWindow(master)
makeWindow(master) now takes in a master widget. This will make
all of the widgets made there be part of the master window.
New_page was modified to make a new Toplevel() widget
TITLE_FRAME is now made first and then grid is called on it
(EDIT) These edits fix the problems with the original window closing the program.
We want to remap the closing behaviour to act how we want. This is done with window.protocol("WM_DELETE_WINDOW",callback). We must define the callback function, in this case, deleteWindow(win).
What delete window does is take a window, and if it is the root window it hides it. Otherwise, it deletes the window. I used window.withdraw() in my code, but there's probably a better way to do it.
The way it knows if it should close the program is by keeping track of the number of active windows in the activeWindows variable. When a window is created, the number increases, when delete it decreases. If the number of active windows is 0, we can delete the main window to close the program cleanly.
The way we bind the deleteWindow(win) callback is through an anonymous function. Normally, the protocol mentioned above does not give any arguments, but we want to know which window called the function. To do this, whenever we bind the destruction of the window, we define a anonymous function using lambda that calls deleteWindow.
.
from tkinter import *
window = Tk()
window.resizable(0,0)
window.configure(background='grey')
window.state('zoomed')
window.geometry("2000x4000")
activeWindows = 1
def deleteWindow(win):
if win == window:
window.withdraw()
else:
win.destroy()
global activeWindows
activeWindows-=1
if activeWindows <= 0:
window.destroy()
#New Window
def New_page():
global activeWindows
activeWindows+=1
NEW_WINDOW=Toplevel(background='grey')
NEW_WINDOW.geometry("2000x4000")
NEW_WINDOW.protocol("WM_DELETE_WINDOW",lambda:deleteWindow(NEW_WINDOW))
makeWindow(NEW_WINDOW)
#Main Window
def makeWindow(master):
#Title Frame
TITLE_FRAME = Frame(master, relief = GROOVE, bg = "black", width=2000, height=160)
TITLE_FRAME.grid(row=0, column=0, columnspan = 150, rowspan = 30, sticky=E+W)
Label(TITLE_FRAME, text= 'THIS IS THE TITLE PART', fg='sky blue', bg='black', font='none 40 bold',
borderwidth=5).grid(row=0,column=10)
#New Window Button
ENTRY_FRAME = Frame(master, bg='sky blue', relief = SUNKEN)
ENTRY_FRAME.grid(row=40, column=0, columnspan=20, padx=15, pady=15)
Label(ENTRY_FRAME, text= 'SELECT THE APPROPRIATE DETAILS:',
bg = 'sky blue', fg='black', font='none 10 bold', borderwidth=5).grid(row=0, column=0, columnspan=20)
NEW_WINDOW = Button(ENTRY_FRAME, text="NEW WINDOW", font='None 8 bold', width=30, command=New_page, fg= 'black', bg='white')
NEW_WINDOW.grid(row = 3, column = 0, columnspan = 3, padx = 10, pady = 10)
window.protocol("WM_DELETE_WINDOW",lambda: deleteWindow(window))
#Calling the Tkinter function
makeWindow(window)
window.mainloop()

Tkinter background with overlapping buttons?

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.

How to draw diagonal arrows in tkinter?

I need to draw two arrows from the blue and green box pointing to the yellow box. I tried drawing diagonal lines using create_line but it didn't work. can anyone please suggest any ways I could draw these arrows.
the error message when using create_line is: AttributeError: '_tkinter.tkapp' object has no attribute 'create_line'
from tkinter import *
import tkinter as tk
window = Tk()
window.geometry("900x500")
window.configure(background='red')
window.title("Theoretical")
label1 = Label(window, text="Hess' cycle of combustion", fg="black", bg="red", font=("Comic Sans MS", 20))
label1.pack()
text1 = Text(window, width=20, height = 1, bg= "blue")
text1.place(x=200, y=100)
window.create_line(0, 0, 200, 100)
window.create_line(0, 100, 200, 0, fill="white")
text2 = Text(window, width=20, height = 1, bg= "green")
text2.place(x=520, y=100)
text3 = Text(window, width=20, height = 1, bg= "yellow")
text3.place(x=370, y=250)
## arrow = Label(window, width=13,height = 1, text = "-------------->", bg= "lawn green", font=("Helvetica", 20))
## arrow.place(x= 330, y=90)
global textbox
textbox = Text(window, width=400, height=10)
textbox.place(x=0, y= 365)
tkinter lines have an arrow option; however, as pointed out in te comments,create_line is a Canvas method: you must therefore use a tk.Canvas object to draw lines:
This minimum example shows you how:
import tkinter as tk
window = tk.Tk()
canvas = tk.Canvas(window)
canvas.pack()
canvas.create_line(0, 0, 200, 100, arrow=tk.LAST)
window.mainloop()
Please note that to avoid "hard to fix" problems and unexpected behavior, it is usually recommended not to import modules in the main namespace (i/e do not from tkinter import *), and not to mix geometry managers ((i/e do not use .place and .pack in the same app)
Edit:
In order to place widgets on a canvas, you must use the Canvas.create_window() method:
import tkinter as tk
window = tk.Tk()
window.geometry("600x600")
canvas = tk.Canvas(window, width=600, height=600)
label_1 = tk.Label(window, text = "from here", anchor = tk.W)
label_1.configure(width = 10, activebackground = "#33B5E5", relief = tk.FLAT)
label_1_window = canvas.create_window(280, 0, anchor=tk.NW, window=label_1)
label_2 = tk.Label(window, text = "to there", anchor = tk.W)
label_2.configure(width = 10, activebackground = "#33B5E5", relief = tk.FLAT)
label_2_window = canvas.create_window(280, 310, anchor=tk.NW, window=label_2)
canvas.pack()
canvas.create_line(300, 40, 300, 300, arrow=tk.LAST)
window.mainloop()

How to center widgets vertically and horizontally in window with Tkinter?

I need to center 3 labels vertically within the window. The labels are centered on-top of each other, but they are fixed at the top of the window.
What do I need to do to have them sit right in the middle of the window, (vertically and horizontally)?
Here is my code:
from tkinter import *
root = Tk()
root.geometry("200x200")
root.title("Question 2")
root.configure(background="green")
Label(root, text = "RED", fg="red", bg="black").pack()
Label(root, text = "WHITE", fg="white", bg="black").pack()
Label(root, text = "BLUE", fg="blue", bg="black").pack()
root.mainloop()
I think that in this case you can simply use a Frame widget as the parent of the labels and then pack the frame by setting the expand option to True:
from tkinter import *
root = Tk()
root.geometry("200x200")
root.title("Question 2")
root.configure(background="green")
parent = Frame(root)
Label(parent, text = "RED", fg="red", bg="black").pack(fill="x")
Label(parent, text = "WHITE", fg="white", bg="black").pack(fill="x")
Label(parent, text = "BLUE", fg="blue", bg="black").pack(fill="x")
parent.pack(expand=1) # same as expand=True
root.mainloop()

Categories