Tkinter Login and Menu Program - python-3.x

I am making a Tkinter Python progarm that will have a Login page and once you are logged in it will show a Menu page for the user to interact with.
My code that includes the Quiz class, StartPage class, Menu class, difficulty class, and the Login page is as follows:
import tkinter as tk
from tkinter import *
import tkinter.messagebox as tm
class Quiz (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 (StartPage, Menu, Difficulty):
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)
label = tk.Label(self, text = "Login")
label.pack(pady = 10 , padx = 10)
Username = tk.Entry(self)
Username.pack()
Password = tk.Entry (self, show = "*")
Password.pack()
button1 = tk.Button(self, text = "Login", command = lambda: Login(Username,Password,parent,controller,self))
button1.pack()
class Menu(tk.Frame):
def __init__ (self, parent, controller) :
tk.Frame.__init__(self, parent)
label = tk.Label(self, text = "Menu")
button1 = tk.Button(self, text = "Histoy", command = lambda: controller.show_frame(Difficulty))
button1.pack()
button2 = tk.Button(self, text = "Maths", command = lambda: controller.show_frame(Difficulty))
button2.pack()
button3 = tk.Button(self, text = "Music",
command = lambda: controller.show_frame(Difficulty))
button3.pack()
class Difficulty(tk.Frame):
def __init__ (self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text = "Difficulty")
Easy = tk.Button(self, text = "Easy", command = lambda: controller.show_frame(Difficulty))
Easy.pack()
Medium = tk.Button(self, text = "Medium",command = lambda: controller.show_frame(Difficulty))
Medium.pack()
Hard = tk.Button(self, text = "Hard", command = lambda: controller.show_frame(Difficulty))
Hard.pack()
backtomenu = tk.Button(self, text = "Back to Menu", command = lambda: controller.show_frame(Menu))
backtomenu.pack()
def Login(Username,Password,parent,controller,self):
Usernames = []
count = 0
Username = Username.get()
Password = Password.get()
try:
with open ("Usernames&Passwords.txt" , "r", encoding = "UTF-8" ) as file:
for each in file:
Usernames.append(each.strip("\n"))
except IOError as error:
print (error)
if Usernames[count] == Username :
if Usernames[count + 1] == Password:
Menu( parent, controller)
print ("Hi")
else:
tm.showinfo("Username or Password is Incorrect")
else:
tm.showinfo("Username or Password is Incorrect")
app = Quiz()
app.geometry ("500x300")
app.mainloop()
When I run the code there is not an error message shown but it doesn't run the Menu class so it does not go to the next Tkinter Frame to continue on with the program. Can someone help point me in the right direction of why the Main class is not running. Thanks in advance.

You have to destroy all other widgets before the next is shown.
Insert self.destroy() before Menu(parent, controller).
The same thing has to be done by the difficulty.
Edit: As #Bryan Oakley pointed out, this is the wrong solution. Instead change Menu(parent, controller) to controller.show_frame(Menu)

Related

How to raise the frame in multiple panned windows if user chooses option in one window that should be reflected in another panned window frame?

I am new to python need help in raising the frames in different panned window if user chooses option in another panned window frame, I will post the code please help me. I choosed combobox for my usecases whenever user chooses any of the usecase and click submit button. I want respective settings for those use cases to be as a frame in the container frame in SettingsUi panned Window frame. Please suggest me any solution.I tried raising frames by creating them as seperate class but facing issue and tried to create the frames with in that SettingUi by checking the combobox conditions and trying to give that function to the submit button in FmUi class.
import tkinter as tk
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText
from tkinter import ttk, VERTICAL, HORIZONTAL, N, S, E, W
class UseCase1(tk.Frame):
def __init__(self,parent):
super().__init__(parent)
ttk.Label(self,text="UseCase1").pack()
# button = tk.Button(self, text="Go to the start page",
# command=lambda:show_frame("UseCase1")).pack()
self.pack()
class UseCase2(tk.Frame):
def __init__(self, parent):
# tk.Frame.__init__(self, parent)
super().__init__(parent)
ttk.Label(self,text="UseCase2").pack()
# label = tk.Label(self, text="This is page 1", font=controller.title_font)
# label.pack(side="top", fill="x", pady=10)
# button = tk.Button(self, text="Go to the start page")
# button.pack()
self.pack()
class UseCase3(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
button = tk.Button(self, text="UseCase3")
button.pack()
class FmUi:
def __init__(self, frame):
# Create a combobbox to select the Usecase level
self.frame = frame
# self.switchframe()
# Create a combobbox to select the Usecase level
values = ['UseCase1', 'UseCase2', 'Usecase3', 'Usecase4', 'Usecase5']
self.level = tk.StringVar()
ttk.Label(self.frame, text='Level:').grid(column=0, row=0, sticky=W)
self.combobox = ttk.Combobox(
self.frame,
textvariable=self.level,
width=25,
state='readonly',
values=values
)
self.combobox.current(0)
self.combobox.grid(column=1, row=0, sticky=(W, E))
self.combobox.bind('<<ComboboxSelected>>', self.on_select)
# # Create a text field to enter a message
# self.message = tk.StringVar()
# ttk.Label(self.frame, text='Message:').grid(column=0, row=1, sticky=W)
# ttk.Entry(self.frame, textvariable=self.message, width=25).grid(column=1, row=1, sticky=(W, E))
self.button = ttk.Button(self.frame, text='Submit',command=SettingsUi.switch_frame(self.combobox.get()))
self.button.grid(column=1, row=1, sticky=W)
# self.frame.grid_columnconfigure(0, weight=1)
# self.frame.grid_rowconfigure(0, weight=1)
def on_select(self, event):
global SummaryText
SummaryText = self.combobox.get()
class SettingsUi(tk.Frame,FmUi):
def __init__(self, frame, *args, **kwargs):
tk.Frame.__init__(self,frame,*args, **kwargs)
self.frame = frame
self._frame = None
self.switch_frame(UseCase1)
def switch_frame(self, frame_class):
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
# container = tk.Frame(self)
# container.pack(side = "top", fill = "both", expand = True)
# container.grid_rowconfigure(0, weight = 1)
# container.grid_columnconfigure(0, weight = 1)
class OutputUi:
def __init__(self, frame):
self.frame = frame
self.scrolled_text = ScrolledText(frame, state='disabled', height=12)
self.scrolled_text.grid(row=0, column=0,sticky=(N, S, W, E))
self.scrolled_text.configure(font='TkFixedFont')
self.frame.grid_columnconfigure(0, weight=1)
self.frame.grid_rowconfigure(0, weight=1)
class App:
def __init__(self, root):
self.root = root
root.title('Automation')
self.menubar =tk.Menu(self.root)
# Adding File Menu and commands
# file = Menu(menubar, tearoff = 0)
# menubar.add_cascade(label ='UseCase', menu = UseCase)
# file.add_command(label ='', command = None)
# file.add_command(label ='', command = None)
# file.add_command(label ='Save', command = None)
# file.add_separator()
# file.add_command(label ='Exit', command = root.destroy)
# Adding Edit Menu and commands
self.Help =tk.Menu(self.menubar, tearoff = 0 , font = ("", 10))
self.menubar.add_cascade(label ='Help ', menu =self.Help, font = ("", 10))
self.Help.add_command(label ='Hotline ', command = None,font = ("", 10))
self.Help.add_command(label ='Documentation', command = None,font = ("", 10))
# edit.add_command(label ='Paste', command = None)
# edit.add_command(label ='Select All', command = None)
# edit.add_separator()
# edit.add_command(label ='Find...', command = None)
# edit.add_command(label ='Find again', command = None)
# Adding Help Menu
self.About=tk.Menu(self.menubar, tearoff = 0,font = ("", 10))
self.menubar.add_cascade(label ='About ', menu = self.About,font = ("", 10))
self.About.add_command(label ='About GUI', command = None,font = ("", 10))
self.About.add_command(label ='Demo', command = None,font = ("", 10))
# help_.add_separator()
# help_.add_command(label ='About Tk', command = None)
# display Menu
root.config(menu = self.menubar)
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
# Create the panes and frames
vertical_pane = ttk.PanedWindow(self.root, orient=VERTICAL)
vertical_pane.grid(row=0, column=0, sticky="nsew")
horizontal_pane = ttk.PanedWindow(vertical_pane, orient=HORIZONTAL)
vertical_pane.add(horizontal_pane)
form_frame = ttk.Labelframe(horizontal_pane, text="Options")
form_frame.columnconfigure(1, weight=1)
horizontal_pane.add(form_frame, weight=1)
console_frame = ttk.Labelframe(horizontal_pane, text="Configuration")
console_frame.columnconfigure(0, weight=1)
console_frame.rowconfigure(0, weight=1)
horizontal_pane.add(console_frame, weight=1)
third_frame = ttk.Labelframe(vertical_pane, text="Console")
vertical_pane.add(third_frame, weight=1)
# GR_frame=ttk.Frame(console_frame)
# EP_frame=ttk.Frame(console_frame)
# Initialize all frames
self.form = FmUi(form_frame)
self.console = SettingsUi(console_frame)
self.third = OutputUi(third_frame)
def quit(self, *args):
self.root.destroy()
def main():
root = tk.Tk()
app = App(root)
app.root.mainloop()
if __name__ == '__main__':
main()
error I am getting
File ~\Documents\SubmissionFolder\untitled29082047.py:168 in
main()
File ~\Documents\SubmissionFolder\untitled29082047.py:163 in main
app = App(root)
File ~\Documents\SubmissionFolder\untitled29082047.py:154 in init
self.form = FmUi(form_frame)
File ~\Documents\SubmissionFolder\untitled29082047.py:62 in init
self.button = ttk.Button(self.frame, text='Submit',command=SettingsUi.switch_frame(self.combobox.get()))
TypeError: switch_frame() missing 1 required positional argument: 'frame_class'

Change Entry widget value from other function

I am quite new in programming with tkinter , especially with classes. How can I make a button that runs function from the same class and changes entry widget. In my code i want to change entry1 whenever button1 is clicked and filepath function runs.
thank you for your help.
Class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
def filepath():
filename = fd.askopenfilename()
entry1.delete(0,END)
entry1.insert(0,filename)
def initUI(self):
self.master.title("EFEKTYWNOŚĆ APP")
self.pack(fill=BOTH, expand=True)
cd = (os.getcwd())
frame1 = Frame(self)
frame1.pack(side = LEFT)
lbl1 = Label(frame1,
text="...",
wraplength = 250 )
lbl1.pack(side=LEFT, padx=5, pady=5)
path = os.path.join(cd, 'ico', '...')
photo = PhotoImage(file = path)
cphoto = photo.subsample(4,4)
button1 = Button(frame1,
text='WYBIERZ PLIK',
image = cphoto,
compound = LEFT,
command = Example.filepath)
button1.image = cphoto
button1.pack(side=LEFT, fill = Y, padx=5, pady=5)
entry1 = Entry(frame1)
entry1.pack(side=LEFT, fill = Y, padx=5, pady=5)
There are some minor things needed to be fixed in your code. I have added a working sample with comments below.
from tkinter import *
from tkinter import filedialog as fd
import os
class Example(Frame):
def __init__(self, master,**kwargs): #have your Frame accept parameters like how a normal frame should
super().__init__(master,**kwargs)
self.master = master #set master as an attribute so you can access it later
self.initUI()
def filepath(self): #add self to make the method an instance method
filename = fd.askopenfilename()
self.entry1.delete(0, END) #use self when referring to an instance attribute
self.entry1.insert(0, filename)
def initUI(self):
self.master.title("EFEKTYWNOŚĆ APP")
self.pack(fill=BOTH, expand=True)
cd = (os.getcwd())
frame1 = Frame(self)
frame1.pack(side=LEFT)
lbl1 = Label(frame1,
text="...",
wraplength=250)
lbl1.pack(side=LEFT, padx=5, pady=5)
path = os.path.join(cd, 'ico', '...')
photo = PhotoImage(file=path)
cphoto = photo.subsample(4, 4)
button1 = Button(frame1,
text='WYBIERZ PLIK',
image=cphoto,
compound=LEFT,
command=self.filepath) #refer to instance methods by self.your_method
button1.pack(side=LEFT, fill=Y, padx=5, pady=5)
self.entry1 = Entry(frame1) #add self to make it an instance attribute
self.entry1.pack(side=LEFT, fill=Y, padx=5, pady=5) #you will then need to use self.entry1 within your class instance
root = Tk()
Example(root)
root.mainloop()

I need help making a tkinter program that variably opens a picture

I'm trying to make a program that has a button that will open a picture if a variable is in a certain state, and change how the button looks (or maybe show a different picture) if it's not. I have been trying to work through the bugs I've been getting.
This is honestly intermediary code so I can understand how to make what I'm actually trying to do, make a network-enabled GUI for some physical buttons.
I've tried passing blueButton in as a variable, but that didn't work.
import tkinter as tk
weather = "sunny"
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.pack()
self.create_widgets()
def create_widgets(self):
self.blueButton = tk.Button(self, fg = "blue")
self.blueButton["text"] = "I'm Blue"
self.blueButton["command"] = self.change
self.blueButton.pack(anchor="nw")
self.quit = tk.Button(self, text = "QUIT", fg = "red",
command = self.master.destroy)
self.quit.pack(side="bottom")
self.pack(fill = "both", expand = 1)
def change(self):
global weather
if weather == "sunny":
w = tk.Canvas(root, width=400, height=750)
img = tk.PhotoImage(file = "haunter.gif")
w.create_image((200, 200), image = img)
w.pack()
else:
self.blueButton["bitmap"] = "error"
root = tk.Tk()
root.geometry("400x300")
app = Application(master = root)
app.mainloop()
The canvas gets made, but the picture doesn't show up, the "quit" button just moves.
I've also gotten the error "name blueButton is not defined".
You could keep the image as an attribute of your App, put it on a canvas, then show or hide the canvas depending on the weather.
import random
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.pack()
self.create_widgets()
def create_widgets(self):
self.blueButton = tk.Button(self, fg = "blue")
self.blueButton["text"] = "I'm Blue"
self.blueButton["command"] = self.change
self.blueButton.pack()
self.quit = tk.Button(self, text = "QUIT", fg = "red",
command = self.master.destroy)
self.quit.pack()
self.pack(fill = "both", expand = 1)
self.canvas = tk.Canvas(root, width=400, height=750)
# self.sunny_img = tk.PhotoImage(file="haunter.gif")
self.sunny_img = tk.PhotoImage(file="rapporteur.gif")
self.canvas.create_image((200, 200), image=self.sunny_img)
def change(self):
weather = ['sunny', 'rainy']
current_weather = random.choice(weather)
if current_weather == 'sunny':
self.canvas.pack()
self.blueButton["bitmap"] = ''
else:
self.canvas.pack_forget()
self.blueButton["bitmap"] = "error"
root = tk.Tk()
root.geometry("400x300")
app = Application(master = root)
app.mainloop()

TypeError: register_user() missing 1 required positional argument: 'self'

import tkinter as tk
import os
import tkinter.messagebox as tm
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.switch_frame(StartPage)
def switch_frame(self, frame_class):
"""Destroys current frame and replaces it with a new one."""
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, text="Please select an option below").pack(side="top", fill="x", pady=10)
tk.Button(self, text="Register",
command=lambda: master.switch_frame(register_screen)).pack()
tk.Button(self, text="Login",
command=lambda: master.switch_frame(login_screen)).pack()
class register_screen(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
global username
global password
global username_entry
global password_entry
self.username = StringVar()
self.password = StringVar()
Label(self, text="Please enter details below").pack()
Label(self, text="").pack()
username_lable = Label(self, text="Username * ")
username_lable.pack()
username_entry = Entry(self, textvariable=self.username)
username_entry.pack()
password_lable = Label(self, text="Password * ")
password_lable.pack()
password_entry = Entry(self, textvariable=self.password, show='*')
password_entry.pack()
Label(self, text="").pack()
Button(self, text="Register", width=10, height=1, command = register_user).pack()
class login_screen(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, text="Login Page").grid(row=0)
global username_verify
global password_verify
self.username_verify = StringVar()
self.password_verify = StringVar()
global username_entry1
global password_entry1
tk.Label(self, text = "Username").grid(row = 3, sticky=E)
username_entry1 = Entry(self,textvariable = username_verify)
username_entry1.grid(row = 3, column = 1)
tk.Label(self, text = "Password").grid(row = 6, sticky=E)
password_entry1 = Entry(self,show="*",textvariable = password_verify)
password_entry1.grid(row = 6, column = 1)
tk.Checkbutton(self, text = "Keep Me Logged In").grid(columnspan = 2)
tk.Button(self,text= "Login", command= login_verify).grid(row = 8)
Got Error: register_user() missing 1 required positional argument: 'self' (or) login_verify() missing 1 required positional argument: 'self'.
I am not understanding what I am missing here. I am new to python so, please explain me using references for my further understanding.Please help me out.if there are any mistakes in the rest of the code or any scope for improvement, please provide the suggestions.
def register_user(self):
username_info = self.username.get()
password_info = self.password.get()
file = open(r"C:\Users\ashita.gadagotti\Desktop\username_info.txt", "w+")
file.write(username_info + "\n")
file.write(password_info)
file.close()
username_entry.delete(0, END)
password_entry.delete(0, END)
Label(self, text="Registration Success.Please log in with the new credentials.", fg="green", font=("calibri", 11),command = lambda: master.switch_frame(login_page)).pack()
def login_verify(self):
username1 = self.username_entry1.get()
password1 = self.password_entry1.get()
username_entry1.delete(0, END)
password_entry1.delete(0, END)
logindetails = os.listdir(r"C:\Users\ashita.gadagotti\Desktop\username_info.txt")
if username1 == logindetails:
file1 = open(username1, "r")
verify = file1.read().splitlines()
if password1 in verify:
master.switch_frame(SearchPage)
else:
tm.showerror("Login error","password has not been recognized")
else:
tm.showerror("Login error","User not found!")
class searchpage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, text="SearchPage").grid(row = 0)
tk.Entry().grid(row = 1)
tk.Button(self, text="Search")
if __name__ == "__main__":
app = SampleApp()
app.title("Equiniti Search Engine")
app.geometry('1280x720')
app.mainloop()
self is a reserved keyword in python, meaning that it has a special meaning in the language. See the answers to this question to learn what it means.In general, it is used as a first argument to methods of class in order to access the reference to the object in question.
From your code, I can see two issues
Indent switch_frame method and its body so that it is recognized as a method of the class
register_user and login_verify seems to be using references to attributes of a class so you need to put them under login_screen class definition

Executing a fuction while passing from a window to an other to get entry value

I want to get the text in the Entry field while passing from Page1 to Page2 and I want to pass it as a parameter to Page2 :
Here is my code
import tkinter as tk
class MyApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
container = tk.Frame(self)
container.pack(side = "top", fill = "both", expand = True)
self.frames ={}
for f in (Page1, Page2):
frame = f(container,self)
self.frames[f] = frame
frame.grid(row = 1000, column = 500, sticky = "nsew")
self.show_frame(Page1)
def show_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()
class Page1(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
Frame0 = tk.Frame(self)
Frame0.pack()
Frame1 = tk.Frame(self)
Frame1.pack()
tk.Label(Frame0,text = "Page 1").pack()
v = tk.StringVar()
def say_hello():
print(v.get())
e = tk.Entry(Frame0, textvariable = v).pack()
tk.Button(Frame1,text = "Page 2", command = (lambda: controller.show_frame(Page2))and say_hello).pack()
class Page2(tk.Frame) :
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
Frame0 = tk.Frame(self)
Frame0.pack()
Frame1 = tk.Frame(self)
Frame1.pack()
tk.Label(Frame0, text="Page 2").pack()
tk.Button(Frame1,text = "Page 1", command = (lambda: controller.show_frame(Page1))).pack()
app = MyApp()
app.mainloop()
How to make this please?
(sorry for my bad English)
If you want the Page1 Entrybox content to be also available in Page2, your best option is to define and store the corresponding StringVar in Page1 and Page2's common controller instance:
class MyApp(tk.Tk):
def __init__(self):
...
# Store the StringVar in MyApp's instance
self.v = tk.StringVar()
...
Then you can access it as controller.v, in Page1:
class Page1(tk.Frame):
def __init__(self,parent,controller):
...
tk.Entry(Frame0, textvariable = controller.v).pack()
tk.Button(Frame1,text = "Page 2",
command=lambda: controller.show_frame(Page2)).pack()
and Page2 as well:
class Page2(tk.Frame) :
def __init__(self,parent,controller):
...
tk.Button(Frame0, text="Print Entry Value",
command=lambda: print(controller.v.get())).pack()

Resources