Tkinter GUI failing to exit - python-3.x

I have a code written and at the top in the file I have the option to Exit which closes the GUI. For some reason when I click "Exit" it doesn't exit. I feel as if there is a simple error that I made when writing this code, but I can't seem to find it. I hope another set of eyes might be able to do so.
#Import tkinter to make gui
from tkinter import *
from tkinter import ttk
#Makes the GUI the same way it was at the beginning of the program
def login(*args):
try:
if (len(name.get())>=2) and (len(pw.get())>=2):
name_entry.delete(0, END)
pw_entry.delete(0, END)
valid.set("")
else:
valid.set("Invalid!")
pass
except TypeError:
valid.set("Invalid!")
pass
except ValueError:
valid.set("Invalid!")
pass
#Sets title and creates gui
root = Tk()
root.title("Login")
topMenu=Menu(root)
root.config(menu=topMenu)
#Creates menu and submenus
subMenu=Menu(topMenu)
#Gives menu options
topMenu.add_cascade(label="File", menu=subMenu)
subMenu.add_command(label="Exit", command=root.quit)
#Configures column and row settings and sets padding
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
name=StringVar()
pw=StringVar()
valid=StringVar()
#Widgets asking name and age
name_entry = ttk.Entry(mainframe, width=15, textvariable=name)
name_entry.grid(column=2, row=1, sticky=(W, E))
pw_entry = ttk.Entry(mainframe, width=15, textvariable=pw)
pw_entry.grid(column=2, row=2, sticky=(W, E))
ttk.Label(mainframe, text="Username").grid(column=1, row=1, sticky=(N, W))
ttk.Label(mainframe, text="Password").grid(column=1, row=2, sticky=(N,W))
#ttk.Label(mainframe, text=" ").grid(column=3, row=3, sticky=(E))
#Makes a button that clears everything and returns it to start of program
ttk.Button(mainframe, text="Login", width=30, command=login).grid(column=2, row=3, columnspan=2, sticky=(W, E))
ttk.Label(mainframe, textvariable=valid).grid(column=1, row=3, sticky=(E))
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)
name_entry.focus()
root.bind('<Return>', login)
root.mainloop()

"try changing root.quit to root.destroy to see if that works any better." (Bryan Oakley)
This managed to do it. I don't know why but root.quit doesn't do it on idle.

Related

How do I fix the following error in Tkinter on __init__ function?

I'm brand new to Tkinter, and am building a tiny UI for interaction with a ML program. Here's the code I'm using for the UI window I've created:
from tkinter import *
from tkinter import ttk
class UI:
def __init__(self, root):
root.title("Retirement Savings Estimator")
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
self.age = IntVar()
self.age = ttk.Entry(mainframe, width=7, textvariable=self.age)
self.age.grid(column=2, row=1, sticky=(W, E))
ttk.Label(mainframe, text ="Enter your age: ").grid(column=1, row=1, sticky=(W, E))
self.yearly_salary = StringVar()
self.yearly_salary = ttk.Entry(mainframe, width=7, textvariable=self.yearly_salary)
self.yearly_salary.grid(column=2, row=2, sticky=(W, E))
ttk.Label(mainframe, text="Enter your gross yearly wages: ").grid(column=1, row=2, sticky=(W, E))
for child in mainframe.winfo_children():
child.grid_configure(padx=5, pady=5)
ttk.Label(mainframe, text="Press the Calculate button to get your estimate: ").grid(column=1, row=3, sticky=(W, E))
action = ttk.Button(mainframe, text="Calculate", default = "active", command = UI).grid(column=2, row=3, sticky=(W, E))
self.age.focus()
root.bind('<Return>', action)
def predict_savings(*args, root):
try:
user_age = int(self.age.get())
yr_salary = float(self.yearly_salary.get())
estimate = regr.predict(user_age, yr_salary)
ttk.Label(mainframe, text="Your Estimated Amount to Save For Retirement: " + estimate).grid(column=1, row=4, sticky=(W, E))
except ValueError:
pass
root = Tk()
UI(root)
root.mainloop()
Here's the error message I'm getting when pressing the 'Calculate' button in the UI window:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\jesst\anaconda3\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
TypeError: __init__() missing 1 required positional argument: 'root'
I've tried adding 'root' to the predict_savings() function to see if this fixes the issue, and a different error generates. I'm not sure what else to try. Any ideas would be excellent.
The error is this line of code:
action = ttk.Button(mainframe, text="Calculate", default = "active", command = UI).grid(column=2, row=3, sticky=(W, E))
You are asking tkinter to create a new instance of UI when the button is clicked. However, UI is defined to need root as one of the parameters. When you click the button, no parameters are passed which is why you get the error.
Since the button exists inside UI, and predict_savings is inside UI, the proper solution is to have the button call self.predict_savings. Also, predict_savings shouldn't require an argument. It doesn't use the arguments so I see no reason to require them. It does, however, require the self parameter like any other class method.
...
action = ttk.Button(..., command = self.predict_savings)...
...
def predict_savings(self):
...
The line below creates a new instance of the class UI.
action = ttk.Button(mainframe, text="Calculate", default = "active", command = UI).grid(column=2, row=3, sticky=(W, E))
When we press the "Calculate" button, we expect to see the estimate, not a new window. The estimate function is self.predict_savings, so we should replace command = UI with command = lambda: self.predict_savings().
action = ttk.Button(mainframe, text="Calculate", default = "active", command = lambda: self.predict_savings()).grid(column=2, row=3, sticky=(W, E))
As #Bryan Oakley, attempting to explain about instantiated class using self.
I do not understand what this is estimate = regr.predict. The regr.predict is defined. I had to remove this.
You had too many an errors.
Add self to self.mainframe to every widget.
Add self in predict_savings parameter. No need for this *args, root. Also ne need to do with trap try/ except.
Using f=string for Label.
Code modified:
from tkinter import *
from tkinter import ttk
class UI:
def __init__(self, root):
root.title("Retirement Savings Estimator")
self.mainframe = ttk.Frame(root, padding="3 3 12 12")
self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
self.age = IntVar()
self.age = ttk.Entry(self.mainframe, width=7, textvariable=self.age)
self.age.grid(column=2, row=1, sticky=(W, E))
ttk.Label(self.mainframe, text ="Enter your age: ").grid(column=1, row=1, sticky=(W, E))
self.yearly_salary = StringVar()
self.yearly_salary = ttk.Entry(self.mainframe, width=7, textvariable=self.yearly_salary)
self.yearly_salary.grid(column=2, row=2, sticky=(W, E))
ttk.Label(self.mainframe, text="Enter your gross yearly wages: ").grid(column=1, row=2, sticky=(W, E))
for child in self.mainframe.winfo_children():
child.grid_configure(padx=5, pady=5)
ttk.Label(self.mainframe, text="Press the Calculate button to get your estimate: ").grid(column=1, row=3, sticky=(W, E))
action = ttk.Button(self.mainframe, text="Calculate", default = "active", command =self.predict_savings).grid(column=2, row=3, sticky=(W, E))
self.age.focus()
root.bind('<Return>', action)
def predict_savings(self):
#try:
user_age = int(self.age.get())
yr_salary = float(self.yearly_salary.get())
estimate = (user_age, yr_salary)
ttk.Label(self.mainframe, text=f"Your Estimated Amount to Save For Retirement: {estimate}").grid(column=1, row=4, sticky=(W, E))
#except ValueError:
#pass
root = Tk()
app = UI(root)
root.mainloop()
Screenshot:
Screenshot after calculated:

Why is the tkinter text widget screwing up my cell sizes?

All was going well as seen in the 1st pic below. all the cells are the same perfect size. its great.
But then comes the implementation of the textbox. and all hell breaks loose. as seen in the 2nd picture it completely disrupts my grid layout. i dont want the textbox adjusting cell sizes, i want it to go where i tell it to go like all the other widgets do. Ive spent hours on this and no avail!
import tkinter as tk
from tkinter import ttk, scrolledtext
root = tk.Tk()
root.state('zoomed')
root.configure(background='#8585ad')
for i in range(0,20):
for x in range(0,20):
root.columnconfigure(i, weight=1)
root.rowconfigure(x, weight=1)
for i in range(0, 20): # 0-19(20 is excluded) so this will loop 10x
for x in range(0, 20):
tk.Label(root, text=f"C-{i}, R-{x}", bg="green", fg="white").grid(column=i, row=x, sticky="NSEW", padx=1, pady=1)
main_frame = tk.Label(root, text="MAIN FRAME", bg="blue", fg="white", anchor="n").grid(column=1, row=1, columnspan=18, rowspan=18, sticky="NSEW")
frame1 = tk.Label(root, text="FRAME 1", bg="red", fg="white", anchor="n").grid(column=2, row=2, columnspan=3, rowspan=16, sticky="NSEW")
frame2 = tk.Label(root, text="FRAME 2", bg="green", fg="white", anchor="n").grid(column=6, row=2, columnspan=6, rowspan=16, sticky="NSEW")
frame3 = tk.Label(root, text=" FRAME 3", bg="red", fg="white", anchor="n").grid(column=13, row=2, columnspan=5, rowspan=16, sticky="NSEW")
for i in range(2, 5): # start at 2 and end after the 3rd loop.
for x in range(3, 18): # to loop 15x and for index to start at 3 so i then put (3,18), 18-3 = 15
tk.Label(root, text=f"Button-{(x-2)}", bg="white", fg="black").grid(column=i, row=x, sticky="EW", padx=5, pady=5)
frame1_header = tk.Label(root, text="User Panel", bg="black", fg="white").grid(column=2, row=2, columnspan=3, sticky="SEW", padx=5, pady=5)
frame2_header = tk.Label(root, text="Editor", bg="black", fg="white").grid(column=6, row=2, columnspan=6, sticky="SEW", padx=5, pady=5)
frame3_header = tk.Label(root, text="Info Panel", bg="black", fg="white").grid(column=13, row=2, columnspan=5, sticky="SEW", padx=5, pady=5)
frame2_text_area = tk.Label(root, text="Text Box", bg="black", fg="white", anchor="center").grid(column=6, row=3, columnspan=4, rowspan=15, sticky="NSEW", padx=5, pady=5)
frame2_list_box = tk.Label(root, text="List Box", bg="grey", fg="white", anchor="center").grid(column=10, row=3, columnspan=2, rowspan=15, sticky="NSEW", padx=5, pady=5)
frame3_tab_panel = ttk.Notebook(root)
frame3_tab_panel.grid(column=13, row=3, columnspan=5, rowspan=15, sticky="NSEW", padx=5, pady=5)
tab1 = ttk.Frame(root)
tab2 = ttk.Frame(root)
tab3 = ttk.Frame(root)
frame3_tab_panel.add(tab1, text ='Generic Editor')
frame3_tab_panel.add(tab2, text ='Text Compare')
frame3_tab_panel.add(tab3, text ='Script Ref')
# width and height does indeed adjust the texbox size but the textbox still isnt properly sticking to the grid that i set.
frame3_tab_panel_tab1 = tk.Text(root, relief="ridge", bd=2, undo=True, wrap="none", background='#1E1E1E', insertbackground='white')#, width=40, height=10)
frame3_tab_panel_tab1.grid(column=13, row=4, columnspan=5, rowspan=14, padx=5, pady=5)
frame3_tab_panel_tab1.config(font=('Consolas bold',10), fg="white")
frame3_tab_panel_tab1.focus()
root.mainloop()
"""
text_area = scrolledtext.ScrolledText(tab1, wrap = tk.WORD, width=40, height=10, font=("Times New Roman", 15))
text_area.grid(column = 0, pady = 10, padx = 10)
text_area.focus()
"""
without textbox. as you can see its all perfectly even.
FYI: this is just a template im working on so i can better understand tk's positioning.
textbox ruining grid by not adjusting itself accordingly and fitting to the grid i set.
There is a lot of wrong doing in your code and you really should take a good tutorial for tkinter and you may wish to have a brief overview of tkinters geometry management.
The biggest issue is whats causes your code to work differently as you expect it, you always define the root as the master. Every widget, except for the root window, has a master and is set by the ONLY positional argument every widget requiers. Note that if None is given, the root window is set by default. This is, because tkinter is built hirachically and at the top of this hirachy stands the root window (the instance of tk.Tk()).
A master should be a container and this means either the root window, a Toplevel or a Frame. Masters can have so called children, which can be every other widget plus frames that are handled as children. The relationship between a master and a frame are various, but for the scope of this question we will just look at the geometry.
Every widget has a geometry and can be received by the universal widget method .winfo_geometry() that will give you a geometry string 'widthxheight±x_offset±y_offset' (e.g. '120x50-0+20'). The geometry string is the basement for every calculations to order your widgets, which you can affect by choosing a geometry manager and different optional keywords. With those information an output will be created and displayed on your screen.
Suggestion:
import tkinter as tk
from tkinter import ttk, scrolledtext
def populate_frame_1():
frame_1_label = tk.Label(frame_1,text='User Panel',
background = 'black',
foreground = 'white')
frame_1_label.grid(column=0,row=0,sticky='ew',columnspan=3)
frame_1.columnconfigure(0,weight=1)
frame_1.columnconfigure(1,weight=1)
frame_1.columnconfigure(2,weight=1)
for i in range(0, 3):
for x in range(1, 16):
l = tk.Button(frame_1, text=f"Button-{(x-2)}",
bg="white", fg="black")
l.grid(column=i, row=x, sticky="EW", padx=5, pady=5)
def populate_frame_2():
frame_2_label = tk.Label(frame_2,text='Editor',
background = 'black',
foreground = 'white')
textbox = tk.Text(frame_2,width=35)
listbox = tk.Listbox(frame_2,bg='yellow')
frame_2_label.grid(column=0,row=0,sticky='ew',columnspan=6)
textbox.grid(column=0,row=1,sticky='ns',columnspan=4)
listbox.grid(column=4,row=1,sticky='ns',columnspan=2)
frame_2.rowconfigure(1,weight=2)
def populate_frame_3():
frame_3_label = tk.Label(frame_3,text='Info Panel',
background = 'black',
foreground = 'white')
frame_3_label.grid(column=0,row=0,sticky='ew',columnspan=5)
control_panel = ttk.Notebook(frame_3)
tab1 = ttk.Frame(control_panel)
tab2 = ttk.Frame(control_panel)
tab3 = ttk.Frame(control_panel)
control_panel.add(tab1, text ='Generic Editor')
control_panel.add(tab2, text ='Text Compare')
control_panel.add(tab3, text ='Script Ref')
control_panel.grid(column=0,row=1,sticky='nswe')
frame3_tab_panel_tab1 = tk.Text(tab1, relief="ridge", bd=2, undo=True,
wrap="none", background='#1E1E1E',
insertbackground='white',width=40, height=10)
frame3_tab_panel_tab1.pack(fill=tk.BOTH,expand=True)
frame3_tab_panel_tab1.config(font=('Consolas bold',10), fg="white")
frame3_tab_panel_tab1.focus()
frame_3.rowconfigure(1,weight=2)
frame_3.columnconfigure(0,weight=2)
XOFFSET = 75
YOFFSET = 50
root = tk.Tk()
root.state('zoomed')
root.configure(background='#8585ad')
main_frame = tk.Frame(root,background='blue')
frame_1 = tk.Frame(main_frame,background='red')
frame_2 = tk.Frame(main_frame,background='green')
frame_3 = tk.Frame(main_frame,background='red')
main_frame.pack(fill=tk.BOTH,expand=True,
padx=XOFFSET,pady=YOFFSET)
frame_1.pack(side=tk.LEFT,fill=tk.BOTH,padx=XOFFSET,pady=YOFFSET,expand=True)
frame_2.pack(side=tk.LEFT,fill=tk.Y,pady=YOFFSET,expand=True)
frame_3.pack(side=tk.LEFT,fill=tk.BOTH,padx=XOFFSET,pady=YOFFSET,expand=True)
populate_frame_1()
populate_frame_2()
populate_frame_3()
root.mainloop()
Change
frame3_tab_panel_tab1.grid(
column=13, row=4, columnspan=5, rowspan=14, padx=5, pady=5
)
to
frame3_tab_panel_tab1.grid(
column=13, row=4, columnspan=5, rowspan=14, padx=5, pady=5,
sticky="NSEW"
)
I managed to solve it by replacing the Text() widget with the scrolledtext.ScrolledText() widget. Its strange. No grid was required and if i remove height and width then it messes it up. Why does height and width have such an impact? why does it even exist when you have things like column and row configure along with sticky. Tkinter is quite confusing sometimes with its logic. But anyways, got there in the end.
Here's the code in case anyone encounters a similar issue.
import tkinter as tk
from tkinter import ttk, scrolledtext
root = tk.Tk()
root.state('zoomed')
root.configure(background='#8585ad')
for i in range(0,20):
for x in range(0,20):
root.columnconfigure(i, weight=1)
root.rowconfigure(x, weight=1)
for i in range(0, 20): # 0-19(20 is excluded) so this will loop 10x
for x in range(0, 20):
tk.Label(root, text=f"C-{i}, R-{x}", bg="green", fg="white").grid(column=i, row=x, sticky="NSEW", padx=1, pady=1)
main_frame = tk.Label(root, text="MAIN FRAME", bg="blue", fg="white", anchor="n").grid(column=1, row=1, columnspan=18, rowspan=18, sticky="NSEW")
frame1 = tk.Label(root, text="FRAME 1", bg="red", fg="white", anchor="n").grid(column=2, row=2, columnspan=3, rowspan=16, sticky="NSEW")
frame2 = tk.Label(root, text="FRAME 2", bg="green", fg="white", anchor="n").grid(column=6, row=2, columnspan=6, rowspan=16, sticky="NSEW")
frame3 = tk.Label(root, text=" FRAME 3", bg="red", fg="white", anchor="n").grid(column=13, row=2, columnspan=5, rowspan=16, sticky="NSEW")
for i in range(2, 5): # start at 2 and end after the 3rd loop.
for x in range(3, 18): # to loop 15x and for index to start at 3 so i then put (3,18), 18-3 = 15
tk.Label(root, text=f"Button-{(x-2)}", bg="white", fg="black").grid(column=i, row=x, sticky="EW", padx=5, pady=5)
frame1_header = tk.Label(root, text="User Panel", bg="black", fg="white").grid(column=2, row=2, columnspan=3, sticky="SEW", padx=5, pady=5)
frame2_header = tk.Label(root, text="Editor", bg="black", fg="white").grid(column=6, row=2, columnspan=6, sticky="SEW", padx=5, pady=5)
frame3_header = tk.Label(root, text="Info Panel", bg="black", fg="white").grid(column=13, row=2, columnspan=5, sticky="SEW", padx=5, pady=5)
frame2_text_area = tk.Label(root, text="Text Box", bg="black", fg="white", anchor="center").grid(column=6, row=3, columnspan=4, rowspan=15, sticky="NSEW", padx=5, pady=5)
frame2_list_box = tk.Label(root, text="List Box", bg="grey", fg="white", anchor="center").grid(column=10, row=3, columnspan=2, rowspan=15, sticky="NSEW", padx=5, pady=5)
frame3_tab_panel = ttk.Notebook(root)
frame3_tab_panel.grid(column=13, row=3, columnspan=5, rowspan=15, sticky="NSEW", padx=5, pady=5)
frame3_tab_panel_tab1 = scrolledtext.ScrolledText(root, bd=2, undo=True, wrap="none", width=40, height=10, font=("Times New Roman", 15), background='#1E1E1E', insertbackground='white')
frame3_tab_panel_tab1.config(font=('Consolas bold',10), fg="white")
frame3_tab_panel_tab1.focus()
tab2 = ttk.Frame(root)
tab3 = ttk.Frame(root)
frame3_tab_panel.add(frame3_tab_panel_tab1, text ='Generic Editor')
frame3_tab_panel.add(tab2, text ='Text Compare')
frame3_tab_panel.add(tab3, text ='Script Ref')
root.mainloop()

How to define specific commands for each button included in each pane of a PanedWindow? [duplicate]

This question already has an answer here:
Tkinter assign button command in a for loop with lambda [duplicate]
(1 answer)
Closed last year.
I want to create a PanedWindow with variable number of panes which every one of these panes includes a label and a button. Pressing a button in a pane should write a messege to the corresponding label in that pane.
I tried this code:
from tkinter import *
from tkinter import ttk
n = 5
root = Tk()
root.geometry('250x500+100+100')
p = ttk.Panedwindow(root, orient=VERTICAL)
p.grid(column=0, row=0, sticky=(N, S, W, E))
for i in range(n):
pane = ttk.Labelframe(p, width=25, borderwidth=0)
p.add(pane)
def writeToLabel():
paneLabel.config(text='This is Pane number %d' %(i+1))
paneLabel = ttk.Label(pane, width=20, relief='solid')
paneButton = ttk.Button(pane, text='Press', command=writeToLabel)
paneButton.grid(column=0, row=0, padx=5)
paneLabel.grid(column=1, row=0, padx=5)
root.rowconfigure(0, weight=1)
root.mainloop()
But no matter which button is pressed the label in the last row is set with the message.
I would be grateful if somebody could help me to fix the problem.
I think this is the sort of thing you are looking for:
from tkinter import *
from tkinter import ttk
n = 5
root = Tk()
root.geometry('250x500+100+100')
p = ttk.Panedwindow(root, orient=VERTICAL)
p.grid(column=0, row=0, sticky=(N, S, W, E))
def writeToLabel(pl, i):
pl.config(text='This is Pane number %d' %(i+1))
for i in range(n):
pane = ttk.Labelframe(p, width=25, borderwidth=0)
p.add(pane)
paneLabel = ttk.Label(pane, width=20, relief='solid')
paneButton = ttk.Button(pane, text='Press', command=lambda pl=paneLabel, i=i: writeToLabel(pl, i))
paneButton.grid(column=0, row=0, padx=5)
paneLabel.grid(column=1, row=0, padx=5)
root.rowconfigure(0, weight=1)
root.mainloop()
Your current method does not work as the definition of writeToLabel will use the last value of paneLabel and i. You instead need to pass a reference to the label and the value of i using a lambda function. The pl=paneLabel and i=i parts of the lambda function are explained here.

Opening a new Window and going back

I have created several individuall windows with tkinter and now I want to connect them.
So implementing several "Forward" and "Back" Buttons. This should be simple but it turns out to screw with me alot.
This can be seen as a practical application issue of this question:
Go back and forth between tkinter windows
I implemented the explained logic the best I can but still fail.
My specific Issues are:
When I klick the "Reports"-button the new window opens but: the
original window(cockpit) doesnt disapear and a second window opens
which is just the Original Cockpit window but without any widgets in
it (just the frame?)
Also when I hit the "Back" Button this error Message Appears:
self.ReportSelection_Win.withdraw() AttributeError: 'Event' object
has no attribute 'ReportSelection_Win'
I stripped the following code of most of its functions since they arent neccessary for the issue I think. So most button dont have any function.
from tkinter import *
from tkinter import ttk
#Funktionen für Fenster
def Func_Show_Rep(self):
# Open new Window
ReportSelection_Win = Tk()
self.ReportSelection_Win = Toplevel()
ReportSelection_Win.title("Report auswählen")
#Dropdown Auswahlliste
Reports = [
"Alle Mitarbeiter",
"Alle Projekte",
"Alle Skills"
]
#Widgets
#Labels & Dropdown
Lbl_Headline = Label(ReportSelection_Win, text = "Bitte wählen Sie einen Report")#Create Label
Lbl_Headline.grid(column=0, row=0, padx=10, pady=10) #Show Label
Drop_Reports = ttk.Combobox(ReportSelection_Win)
Drop_Reports.grid(column=0, row=1, padx=10, pady=10)
Drop_Reports['values'] = Reports
#Buttons
Btt_Confirm_RepSelect = Button(ReportSelection_Win, text="Auswählen")
Btt_Confirm_RepSelect.bind("<Button-1>", Select_Report)
Btt_Confirm_RepSelect.grid(column=0, row=2, padx=10, pady=10, sticky=W)
Btt_Back_RepSelect = Button(ReportSelection_Win, text="Zurück")
Btt_Back_RepSelect.bind("<Button-1>", Func_ReportSelection_Back)#Back to Cockpit
Btt_Back_RepSelect.grid(column=0, row=2, padx=10, pady=10, sticky=E)
self.Cockpit_Win.withdraw() #.deiconify() to show again
#Funktionen für Report Fenster
def Func_ReportSelection_Back(self):
self.ReportSelection_Win.withdraw()
self.Cockpit_Win.deiconify()
#Modify the Window [◙Not essential for Issue]
Cockpit_Win.title("Ressourcen Verwaltung")
Cockpit_Win.columnconfigure(1, weight=1)
Lbl_Descr_MA = Label(Cockpit_Win, text = "Mitarbeiter verwalten und anlegen")#Create Label
Lbl_Descr_MA.grid(column=0, row=0, padx=10) #Show Label
Btt_Show_MA = Button(Cockpit_Win, text="Mitarbeiter", width=35)
Btt_Show_MA.bind("<Button-1>",Func_Show_MA)#Button click starts function
Btt_Show_MA.grid(column=1, row=0, padx=10, pady=7, sticky=E)
Lbl_Descr_Pro = Label(Cockpit_Win, text = "Projekte Verwalten und anlegen.")#Create Label
Lbl_Descr_Pro.grid(column=0, row=1, padx=10) #Show Label
Btt_Show_Pro = Button(Cockpit_Win, text="Projekte", width=35)
Btt_Show_Pro.bind("<Button-1>",Func_Show_Pro)#Button click starts function
Btt_Show_Pro.grid(column=1, row=1, padx=10, pady=7, sticky=E)
Lbl_Descr_Rep = Label(Cockpit_Win, text = "Report auswählen und ausgeben")#Create Label
Lbl_Descr_Rep.grid(column=0, row=2, padx=10) #Show Label
Btt_Show_Rep = Button(Cockpit_Win, text="Reports", width=35)
Btt_Show_Rep.bind("<Button-1>",Func_Show_Rep)#Button click starts function
Btt_Show_Rep.grid(column=1, row=2, padx=10, pady=7, sticky=E)
Btt_Cock_Abort = Button(Cockpit_Win, text="Abbrechen", width=35)
Btt_Cock_Abort.bind("<Button-1>",Func_Cock_Abort)#Button click starts function
Btt_Cock_Abort.grid(column=1, row=3, padx=10, pady=7, sticky=E)
Cockpit_Win.geometry('350x170') #Window size
#Make the windows stay (loop)
Cockpit_Win.mainloop()
I reduced your code to almost minimal working case.
from tkinter import *
from tkinter import ttk
#Funktionen für Fenster
def Func_Show_Rep(even = None):
global Cockpit_Win
Cockpit_Win.withdraw()#.deiconify() to show again
ReportSelection_Win = Toplevel()
Show_Rep(ReportSelection_Win, Cockpit_Win)
class Show_Rep():
# Hide old Window
def __init__(self, master, Cockpit_Win):
# Open new Window
self.ReportSelection_Win =master
self.ReportSelection_Win.title("Report auswählen")
#Dropdown Auswahlliste
Reports = [
"Alle Mitarbeiter",
"Alle Projekte",
"Alle Skills"
]
#Widgets
#Labels & Dropdown
Lbl_Headline = Label(self.ReportSelection_Win, text = "Bitte wählen Sie einen Report")#Create Label
Lbl_Headline.grid(column=0, row=0, padx=10, pady=10) #Show Label
Drop_Reports = ttk.Combobox(self.ReportSelection_Win)
Drop_Reports.grid(column=0, row=1, padx=10, pady=10)
Drop_Reports['values'] = Reports
#Buttons
Btt_Back_RepSelect = Button(self.ReportSelection_Win, text="Zurück")
Btt_Back_RepSelect.bind("<Button-1>", self.Func_ReportSelection_Back)#Back to Cockpit
Btt_Back_RepSelect.grid(column=0, row=2, padx=10, pady=10, sticky=E)
#Funktionen für Report Fenster
def Func_ReportSelection_Back(self, event = None):
self.ReportSelection_Win.withdraw()
Cockpit_Win.deiconify()
Cockpit_Win = Tk()
#Modify the Window [◙Not essential for Issue]
Cockpit_Win.title("Ressourcen Verwaltung")
Cockpit_Win.columnconfigure(1, weight=1)
Lbl_Descr_Rep = Label(Cockpit_Win, text = "Report auswählen und ausgeben")#Create Label
Lbl_Descr_Rep.grid(column=0, row=2, padx=10) #Show Label
Btt_Show_Rep = Button(Cockpit_Win, text="Reports", width=35)
Btt_Show_Rep.bind("<Button-1>",Func_Show_Rep)#Button click starts function
Btt_Show_Rep.grid(column=1, row=2, padx=10, pady=7, sticky=E)
Cockpit_Win.geometry('350x170') #Window size
#Make the windows stay (loop)
Cockpit_Win.mainloop()
Explanation:
I crated class that writes your reports to window.
And function that hides your main_window, makes Topwindow

How to create a sub frames with a specific layout?

I'm aiming to make a login program but the only part that confuses me is how to make the frames.I need 3 different frames but I neither know how to make a frame other the then like this:
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
and I can only make labels and widgets using that single mainframe. As far as making another one, it is beyond me. I need to know exactly place widets inside of each frame and even after creating frames I don't know how to place stuff on the grid. Would I go for the overall grid, or does something change after making the grid. I'm using the following layout for making the frame. Basically i'm hoping for a crash course in frames. Any information i've gathered doesn't make sense to me, even after I tried to put it into code.
I've got the coding part down just not the frame part.
#Import tkinter to make gui
from tkinter import *
from tkinter import ttk
import codecs
def login(*args
):
file = open("rot13.txt", "r")
lines = file.readlines()
uname = user.get()
pword = pw.get()
for i in lines:
x = i.split()
if codecs.encode(uname,'rot13') == x[0] and codecs.encode(pword,'rot13') == x[1]:
result.set("Successful")
break;
else:
result.set("Access Denied")
root = Tk()
root.title("Login")
#Configures column and row settings and sets padding
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
user = StringVar()
pw = StringVar()
result = StringVar()
user_entry = ttk.Entry(mainframe, width=20, textvariable=user)
user_entry.grid(column=2, row=1, sticky=(W, E))
pw_entry = ttk.Entry(mainframe, width=20, textvariable=pw)
pw_entry.grid(column=2, row=2, sticky=(W, E))
ttk.Label(mainframe, text="Username ").grid(column=1, row=1, sticky=W)
ttk.Label(mainframe, text="Password ").grid(column=1, row=2, sticky=W)
ttk.Label(mainframe, text="").grid(column=1, row=3, sticky=W)
ttk.Label(mainframe, text="Result").grid(column=1, row=4, sticky=W)
ttk.Label(mainframe, text="").grid(column=1, row=5, sticky=W)
ttk.Button(mainframe, text="Login", command=login).grid(column=3, row=6, sticky=W)
#Makes a spot to put in result
ttk.Label(mainframe, textvariable=result).grid(column=2, row=4, sticky=(W, E))
#Opens up with item selected and allows you to enter username without having to click it
user_entry.focus()
#Runs calculate if click enter
root.bind('<Return>', login)
root.mainloop()
I believe the key point that you are missing is that subframes of mainframe use mainframe as the parent and that widgets within subframes use the subframe as parent. Furthermore, you can then place the subframe within the mainframe and the subframe widgets within the subframe. You do not have to pass parents to .grid because each widget knows its parent. A simplified example:
from tkinter import *
root = Tk()
mainframe = Frame(root)
login = Frame(mainframe)
label = Label(login, text='label')
entry = Entry(login)
display = Frame(mainframe)
result = Label(display, text='display result')
mainframe.grid() # within root
login.grid(row=0, column=0) # within mainframe
label.grid(row=0, column=0) # within login
entry.grid(row=0, column=1) # within login
display.grid() # within mainfram
result.grid(row=2, column=0) # within display

Resources