Python tkinter- getting user input and checking it - python

I'm fairly new to Python but I'm trying to learn as I go along. I'm using a raspberry Pi and I'm using Python version 3.2.3. My question is I have a text widget in my frame which lets users add text. I've got a button below called "run code" and when this is clicked it calls a function which should check the input from the text box. If the character is alphabetical it then prints to a label a welcome message and my score should increase by 5 points, if the input is not alphabetical it shows an error message. I've tried to use an if statement but only the else section is performing. Any suggestions? My code is below:
import tkinter as tk
from tkinter import ttk
score = 0
class Game(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Game")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
menubar = tk.Menu(container)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Exit", command=quit)
menubar.add_cascade(label="File", menu=filemenu)
tk.Tk.config(self, menu=menubar)
self.frames = {}
for F in (StartPage, Py2Page1):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column = 0, sticky = "nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
self.columnconfigure(0,weight=1)
self.columnconfigure(1,weight=1)
label = tk.Label(self, text="Title")
label.grid(row=0,column=0, columnspan=2)
label1 = tk.Label(self, text ="Add text here")
label1.grid(row=1,column=0, columnspan=2, pady=10)
button1 = ttk.Button(self, text="Start", command=lambda: controller.show_frame(Py2Page1))
button1.grid(row=2,column=0, columnspan=2,pady=10)
class Py2Page1(tk.Frame):
def __init__(self, parent,controller):
tk.Frame.__init__(self, parent)
result = tk.StringVar()
self.columnconfigure(0,weight=1,minsize=640)
self.columnconfigure(1,weight=1,minsize=640)
label = tk.Label(self, text="Title!")
label.grid(row=0,column=0,columnspan=2)
self.status = tk.Label(self)
self.status.grid(row=0,column=1,sticky="e",padx=30)
label2 = tk.Label(self, text ="""SubTitle""")
label2.grid(row=1,column=0)
label3 = tk.Label(self, text ="""
Add text here....
""", justify="left")
label3.grid(row=2,column=0,sticky="n")
self.user_input = tk.Text(self,wrap="word")
self.user_input.grid(column=1,row=2)
button4 = ttk.Button(self,text="Run Code", command = self.checking)
button4.grid(column=1,row=3)
button5 = ttk.Button(self,text="Clean", command = self.clear)
button5.grid(column=1,row=4)
self.output = tk.Label(self)
self.output.grid(column=1,row=5,sticky='w', pady=10,padx=10)
def checking(self):
answer = self.user_input.get('1.0',tk.END)
if answer.isalpha():
result = "Hello " + answer
scorechanged= score =+ 5
else:
result = "Please enter your name again"
self.output.config(text=result)
self.status.config(text=scorechanged)
def clear(self):
self.user_input.delete('1.0',tk.END)
app = Game()
app.geometry("1280x720")
app.mainloop()
Thanks

Addressing the initial question:
userInput = stringVar()
userEntry = Entry(master, variable=userInput) #creates an entry box
userInput.get() # returns what is in the entry box
I could imagine with this code you can accomplish what you intend to. You can use if statements to see what is in the entry box and determine weather it is a number.
try:
int(userInput.get()) # try and convert to integer
except ValueError: # if the conversion fails due to it containing letters
print('userInput is not a number')

Related

Accessing variables outside class scope Python for tkinter app

I'm making an application using tkinter, and I want to access global variable that I assign a value to from a tkinter Entry by a user. I'm following an MVC pattern for the creation of the application, and every window is in it's own class and I'm struggling basically with using data from one class to the next. In this context, I want to print the username entered by the user into the label in the class PageThree I've made a minimum reproduceable version of the code here:
import tkinter as tk
from tkinter import font as tkfont
from tkinter import messagebox
stored_username = "Tessa"
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (PageTwo, PageThree):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("PageTwo")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.label_username_signup = tk.Label(self, text="Username")
self.label_password_signup = tk.Label(self, text="Password")
self.entry_username_signup = tk.Entry(self)
self.entry_password_signup = tk.Entry(self, show="*")
self.label_username_signup.grid(row=0, sticky=tk.E)
self.label_password_signup.grid(row=1, sticky=tk.E)
self.entry_username_signup.grid(row=0, column=1)
self.entry_password_signup.grid(row=1, column=1)
self.rgbtn = tk.Button(self, text="Register", command=self.log_details)
self.rgbtn.grid(columnspan=3)
button = tk.Button(self, text="Back",
command=lambda: controller.show_frame("StartPage"))
button.grid()
def log_details(self):
username = self.entry_username_signup.get()
global stored_username
stored_username = username
if username:
self.controller.show_frame("PageThree")
else:
tk.messagebox.showerror("Login Failure", "Incorrect username or password, please try again")
class PageThree(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
self.controller = controller
global stored_username
lbl = tk.Label(self,text=name_entry)
lbl.grid(row=0,column=0)
def name_entry():
global stored_username
string = stored_username.get()
return string
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
I think the closest thing to a related question I can find is: Taking input from the user in Tkinter
However they are not dealing with modular classes.

Tkinter: Code stops and window doesn't show up

I am working on a very basic interface on Python with Tkinter, that displays two input boxes and a button to login. I try to do it by creating different frames and change the frame when the user is logged. It was working nearly fine but then the code started to execute itself not entirely sometimes and entirely but without the Tkinter window. I looked into it and saw nothing shocking but I am not an expert so I am looking for help.
This is the code to run my class that implement Tkinter window:
print 1
app = Skeleton("HomePage")
print 2
app.mainloop()
print 3
The skeleton Class that implement the Tkinter window:
class Skeleton(Tk):
def __init__(self, f,*args, **kwags):
Tk.__init__(self,*args, **kwags)
self.title(f)
container = Frame(self, width=512, height=512)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
frameName = {"home","upload","retrieve","deconnected"}
self.frames["HomePage"] = HomePage(parent= container, controller=self)
self.frames["HomePage"].grid(row=0, column=0, sticky="nsew")
print 321
self.show_frame("HomePage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
print "Je vais te montrer mon frame"
frame = self.frames[page_name]
frame.tkraise()
And the code of the Home Page frame:
class HomePage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.parent = parent
self.controller = controller
#print ("Construction de la page dáccueil")
#LABEL
self.username = Label(self, text="Username:")
self.username.grid(row =0,column =0)
self.username.pack()
#ENTRY
self.username_txb = Entry( self)
self.username_txb.focus_set()
self.username_txb.grid(row =0,column =1)
self.username_txb.pack(side=LEFT)
#LABEL
self.pass_lbl = Label(self, text="Password:")
self.pass_lbl.grid(row =0,column =2)
#ENTRY
self.password_txb = Entry( self, text="Password", show = "*")
self.password_txb.grid(row =0,column =3)
self.password_txb.pack(side=LEFT)
#LOGIN BUTTON
self.login_btn = Button(self, text="Login", command=lambda: controller.show_frame("UploadPage"))
self.login_btn.grid(row =0,column =4)
self.login_btn.pack(side=LEFT)
self.info_pane = PanedWindow()
self.info_pane.grid(row =1,column =0)
self.info_pane.pack(fill="none", expand=True, side=BOTTOM)
self.info_lbl = Label(self, text="More information about access:", fg="blue", cursor="hand2")
self.contact_lbl = Label(self, text="Contact us", fg="blue", cursor="hand2")
self.contact_lbl.grid(row =2,column =0)
self.contact_lbl.pack()
self.contact_lbl.bind("<Button-1>", self.callback)
print ("123Construction de la page dáccueil")
#self.parent.update()
def callback(self, event):
pass
def connect(self,controller ):
login = self.username_txb.get()
pwd = self.password_txb.get()
if(login == "a" and pwd == "a"):
print "Valid account"
self.controller.show_frame("UploadPage")
#UploadPage frame is implemented
The output everytime I execute the code is as following:
1
123Construction de la page dáccueil
Thank you in advance for the help. Hope this will help other people.
First lets address your use of pack() and grid().
Due to how tkinter is set up you cannot use both pack() and grid() on the same widget in a frame or window at one time.
You may use for example pack() to pack the main frame and grid() on the widgets inside that frame but you cannot use both in side the frame.
If one of your issues is where each widget is located and if it is expanding with the window you can manage all that inside of grid() so we can just use grid() here as its what I prefer when writing up a GUI.
Next we need to look at your call to show_frame as you are attempting to show a frame that does not exist in self.frames in the code you have presented us.
I have created a new class so your program can be tested with this line of code:
self.controller.show_frame("UploadPage")
The new class just makes a basic frame with a label in it showing that the frame does rise properly with tkrise().
I did some general clean up as your show_frame method was taking unnecessary steps to raise the frame, your method of importing tkinter is not the best option and some other quality corrections.
Instead of using:
frame = self.frames[page_name]
frame.tkraise()
We can simplify this method with just one line like this:
self.frames[page_name].tkraise()
I have also changed how you are importing tkinter as importing with * can sometimes cause problems if you inadvertently override build in methods. The best option is to import tkinter like this:
import tkinter as tk
Take a look at the below code and let me know if you have any questions. It should provide the info you need to allow the HomePage frame and UploadPage frame to work as intended.
import tkinter as tk
class Skeleton(tk.Tk):
def __init__(self, f,*args, **kwags):
tk.Tk.__init__(self,*args, **kwags)
self.title(f)
self.container = tk.Frame(self, width=512, height=512)
self.container.grid(row=0, column=0, sticky="nsew")
self.container.grid_rowconfigure(0, weight=1)
self.container.grid_columnconfigure(0, weight=1)
self.frames = {}
self.frames["HomePage"] = HomePage(parent=self.container, controller=self)
self.frames["HomePage"].grid(row=0, column=0, sticky="nsew")
self.frames["UploadPage"] = UploadPage(parent=self.container)
self.frames["UploadPage"].grid(row=0, column=0, sticky="nsew")
self.show_frame("HomePage")
def show_frame(self, page_name):
self.frames[page_name].tkraise()
class HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.parent = parent
self.controller = controller
self.username = tk.Label(self, text="Username:")
self.username.grid(row =0,column =0)
self.username_txb = tk.Entry(self)
self.username_txb.focus_set()
self.username_txb.grid(row=0, column=1)
self.pass_lbl = tk.Label(self, text="Password:")
self.pass_lbl.grid(row =0,column =2)
self.password_txb = tk.Entry(self, text="Password", show="*")
self.password_txb.grid(row =0,column =3)
self.login_btn = tk.Button(self, text="Login", command=self.connect)
self.login_btn.grid(row=0, column=4)
self.info_pane = tk.PanedWindow()
self.info_pane.grid(row=1, column=0)
self.info_lbl = tk.Label(self, text="More information about access:", fg="blue", cursor="hand2")
self.contact_lbl = tk.Label(self, text="Contact us", fg="blue", cursor="hand2")
self.contact_lbl.grid(row=2, column=0)
self.contact_lbl.bind("<Button-1>", self.callback)
def callback(self, event):
pass
# webbrowser.open_new("https://www.tno.nl/nl/")
# I do not have the import for this webbrowser so I disabled it for testing.
def connect(self):
login = self.username_txb.get()
pwd = self.password_txb.get()
if(login == "a" and pwd == "a"):
self.controller.show_frame("UploadPage")
class UploadPage(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
tk.Label(self, text="This upload frame is a test to see if your code is working").grid(row=0, column=0)
if __name__ == "__main__":
app = Skeleton("HomePage")
app.mainloop()

Label Tkinter Variable

I created a quiz in tkinter , which goes from page to page and adding to the variable "score".
But if i want to display the final score it shows the initial value instead of the actual one.
Does somebody have a similar problem or an idea for a solution?
Thanks
import tkinter as tk
from tkinter import font as tkfont
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage,theme1page,theme2page,theme1Q1,theme1Q2,theme1Q3,\
theme1Q4,theme1Q5,theme2Q1,theme2Q2,theme2Q3,theme2Q4,theme2Q5, Results):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
We directly show the last question page for simplicity. The variable score is the one we increase while answering correctly.
class theme1Q5(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="5.Question", font=controller.title_font)
label.pack(side="top", fill="x")
Question15 = tk.Label(self, text="Which sentence is not true?")
Question15.place(x=0, y = 30)
controll15 = tk.IntVar()
wrong151 = tk.Radiobutton(self, text="Neural Networks work bad with small amount of data", \
variable= controll15,value=1)
wrong152 = tk.Radiobutton(self, text="Concept of neural network exists since the middle of the mid-twentieth",\
variable= controll15,value=0)
right15 = tk.Radiobutton(self, text="There is no learning rate parameter in training neural networks", \
variable= controll15,value=5)
wrong151.place(x=0, y=60)
wrong152.place(x=0, y=80)
right15.place(x=0, y=100)
def scorer(event):
if int(controll15.get()) > 2:
global score
score += 1
button = tk.Button(self, text="Result",command = lambda: controller.show_frame("Results") )
button.bind("<Button-1>", scorer)
button.pack(side="right")
#END THEME 1
This is the page for showing the actual result (score value). Problem is, while answering all questions correctly, it will show the score initial value (0). On the other hand, the scorecalc function assigned to "print score" button shows the right score... Seems like it can't show from first the actual value, but we have to click on a button to do so...
#RESULT PAGE
class Results(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Your Score:", font=controller.title_font)
label.pack(side="top", fill="x")
button = tk.Button(self, text="return to Menu",
command=lambda: controller.show_frame("StartPage"))
button.pack(side= "bottom")
global score
label = tk.Label(self, text= "%s / 5" %(score), font=controller.title_font)
label.pack()
def scorecalc():
label = tk.Label(self, text="Your Score:", font=controller.title_font)
label.pack(side="top", fill="x")
label = tk.Label(self, text= "%s / 5" %(score), font=controller.title_font)
label.pack()
scorep= tk.Button(self, text ="print score", command=scorecalc)
scorep.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
There are some major issues with your code. Using global variables while using classes is counter productive I think.
One of the major reason why your code does not work is due to the fact you are using variables where class attributes should be used. If you use a variable in a class then after __init__ you will not be able to interact with that variable. be it a widget or a save value like a number or string.
We can fix this by adding the self. prefix to anything that is going to be interacted with from inside the class or from outside the class object.
Also your code does not actually show that you have a global variable called score so I added one to the global namespace for testing.
with that in mind you were using the variable name label for multiple labels. any time you are assigning a variable name they need to be unique.
I have combined the 3 sections of your code to provide a working example that will update the score. This example is not perfect but it is the minimum that is needed to be changed to get the results you are looking for.
Let me know if you have any question:
import tkinter as tk
from tkinter import font as tkfont
score = 1
class theme1Q5(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="5.Question", font=controller.title_font)
label.pack(side="top", fill="x")
Question15 = tk.Label(self, text="Which sentence is not true?")
Question15.place(x=0, y = 30)
self.controll15 = tk.IntVar()
wrong151 = tk.Radiobutton(self, text="Neural Networks work bad with small amount of data",
variable= self.controll15,value=1)
wrong152 = tk.Radiobutton(self, text="Concept of neural network exists since the middle of the mid-twentieth",
variable= self.controll15,value=0)
right15 = tk.Radiobutton(self, text="There is no learning rate parameter in training neural networks",
variable= self.controll15,value=5)
wrong151.place(x=0, y=60)
wrong152.place(x=0, y=80)
right15.place(x=0, y=100)
button = tk.Button(self, text="Result",command = lambda: controller.show_frame("Results"))
button.bind("<Button-1>", self.scorer)
button.pack(side="right")
def scorer(self, event = None):
if int(self.controll15.get()) > 2:
global score
score += 1
self.controller.frames["Results"].update_label()
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (theme1Q5, Results):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("theme1Q5")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
#RESULT PAGE
class Results(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Your Score:", font=controller.title_font)
label.pack(side="top", fill="x")
button = tk.Button(self, text="return to Menu",
command=lambda: controller.show_frame("theme1Q5"))
button.pack(side= "bottom")
global score
self.label2 = tk.Label(self, text= "%s / 5" %(score), font=self.controller.title_font)
self.label2.pack()
def update_label(self):
global score
self.label2.config(text= "%s / 5" %(score))
print(score)
if __name__ == "__main__":
app = SampleApp()
app.mainloop()

Python (Tkinter): Unable to save user inputs to a variable using .get() [duplicate]

This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 5 years ago.
I am in the process of creating a UI using tkinter for a program I have written in Python2.7. I have modified code I found here: Switch between two frames in tkinter
The way I was hoping the code would work is that when the "Apply" button is pressed, the method varset1 or varset2 (depending on the current page) would be called and this should save the user inputs to variables using the .get() command.
However, when I attempt to save the user inputted entries (Initial, LastName, HouseNo and PostCode) to variables, this error message is returned:
AttributeError: 'NoneType' object has no attribute 'get'
Here is a simplified version of my code, it is still a bit long, though this is as concise as I could make it in order to reproduce the error:
import Tkinter as tk
class Setup(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (page1, page2):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("page1")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class page1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
tk.Label(self, text="First Initial: ").grid(row=2, sticky=tk.E)
self.Initial = tk.Entry(self).grid(row=2, column=1)
tk.Label(self, text="Last Name: ").grid(row=3, sticky=tk.E)
self.LastName = tk.Entry(self).grid(row=3, column=1)
Quit = tk.Button(self, text="Exit",
command= self.quit).grid(row=13, column=0, sticky="sw")
Next = tk.Button(self, text="OK",
command=lambda: controller.show_frame("page2")).grid(
row=13, column=1, sticky=tk.SE)
Apply = tk.Button(self, text="Apply",
command = self.varset1).grid(row=13, column=1,
sticky=tk.SW)
def varset1(self):
initial = self.Initial.get()
lastname = self.LastName.get()
class page2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
tk.Label(self, text="House Number: ").grid(row=2, sticky=tk.E)
self.HouseNo = tk.Entry(self).grid(row=2, column=1)
tk.Label(self, text="Post Code: ").grid(row=3, sticky=tk.E)
self.PostCode = tk.Entry(self).grid(row=3, column=1)
Quit = tk.Button(self, text="Exit",
command= self.quit).grid(row=13, column=0, sticky="sw")
Back = tk.Button(self, text="Back",
command=lambda: controller.show_frame("page1")).grid(
row=13, column=1, sticky=tk.SE)
Apply = tk.Button(self, text="Apply",
command = self.varset2).grid(row=13, column=1,
sticky=tk.SW)
def varset2(self):
houseno = self.HouseNo.get()
postcode = self.PostCode.get()
if __name__ == "__main__":
app = Setup()
app.mainloop()
I really appreciate any help!
Every variables you made to assign Entry and Button are grided using this format:
self.Initial = tk.Entry(self).grid(row=2, column=1)
which is wrong because tk.Entry(self) returns the Entry object, but tk.Entry(self).grid(row=2, column=1) returns None. So self.Initial is actually None. What you need to do is to split it into two lines like this for every Entry or Button that you're going to retrieve data from:
self.Initial = tk.Entry(self)
self.Initial.grid(row=2, column=1)
You should change every one of those for connivance and to avoid further similar errors(which is what you should've done in the first place)...
self.LastName = tk.Entry(self).grid(row=3, column=1)
# into:
self.LastName = tk.Entry(self)
self.LastName.grid(row=3, column=1)
# and so on....

Python Object Oriented Tkinter - Calling Function Error

I have a login button on the Login frame, I want the login button to only take me to the AdminHome frame if "valid" is entered in the username entry. I can't get the show_frame() function to run in the validate() function (located in the Login Class).
I get the error:
NameError: global name 'show_frame' is not defined
How would I overcome this error and get it to run?
import tkinter as tk
from tkinter import ttk
class Program(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (Login, AdminHome):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky = "nsew")
self.show_frame(Login)
def show_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()
class Login(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
innerFrame = tk.Frame(self)
innerFrame.place(relx=.5, rely=.5, anchor="c")
pagename = tk.Label(innerFrame, text = "iDea Academy Progress Tracker Login")
pagename.grid(row=0, columnspan=5, sticky="W"+"E")
username = tk.Label(innerFrame, text="Username: ")
username.grid(row=1, columnspan=2, sticky="W")
self.user = ttk.Entry(innerFrame, text ="", width=45)
self.user.grid(row=1, column=2 ,columnspan=3, sticky="w")
password = tk.Label(innerFrame, text="Password: ")
password.grid(row=2, columnspan=2, sticky="W")
self.passentry = ttk.Entry(innerFrame, text ="", width=45, show="*")
self.passentry.grid(row=2, column=2 ,columnspan=3, sticky="W")
login = ttk.Button(innerFrame, text = "Login", command = self.validate)
login.grid(row=3, columnspan=5, sticky="W"+"E")
def validate(self):
if self.user.get()=="valid":
show_frame(AdminHome)
class AdminHome(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
fetch = ttk.Button(self, text = "Fetch Data", command = lambda: controller.show_frame(AdminHome))
fetch.grid(row=2, columnspan=6, sticky="W"+"E")
app = Program()
app.state('zoomed')
app.mainloop()
Here is the way I would do it: I would get rid of the validate method in your login frame, and seperately define a function for validation. This would look like this:
def validate(user):
global app
print(user)
if user=="valid":
app.show_frame(AdminHome)
Then, in your command for the login button, simply change it to be: lambda: validate(self.user.get()).

Categories