Why are my widgets not showing up on the 3rd screen - python

When you select 2 duelist on the second screen the program shows a 3rd screen that should display 2 labels and 2 entry widgets for the user to enter the names of the players. But I can't seem to figure out why the widgets are not showing up. The section of code that involves this issue is the the block for the class TwoPlayer. Thank you!
import tkinter as tk
largeFont = ("Veranda", 18)
field1 = 'Duelist 1', 'Duelist 2'
names = []
class Yugioh_backEnd(tk.Tk):
#set default initializion
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "YuGiOh Duel Calculator")
#containers
container = tk.Frame(self)
#set pack method for container
container.pack(side="top", fill="both", expand=True)
#set grid method for container
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
#selects which frame to show
self.frames = {}
for F in (StartPage, NumPlayers, TwoPlayer):
frame = F(container, self)
self.frames[F]=frame
frame.grid(row=0, column=0, sticky="nsew")
#show Frame
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)
#greet the user
greeting = tk.Label(self, text = "Welcome to\n YuGiOh Duel Calculator!", font = largeFont)
greeting.pack(pady=(10,40),padx=30)
#Enter the next window
lets_duel = tk.Button(self, text="Lets Duel!!!", command=lambda: controller.show_frame(NumPlayers))
lets_duel.pack(pady=(0,30),padx=30)
class NumPlayers(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
#prompt for players quantity
prompt1 = tk.Label(self, text = "How many duelist?", font = largeFont)
prompt1.pack(pady=(10,40),padx=30)
#Number of players
twoPlayers = tk.Button(self, text = "2 Duelists", command=lambda: controller.show_frame(TwoPlayer))
return1 = tk.Button(self, text="Return Home", command=lambda: controller.show_frame(StartPage))
#Add buttons to frame
return1.pack(pady=(0,30),padx=30)
twoPlayers.pack(pady=(0,10),padx=30)
#Two player mode
class TwoPlayer(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
def makeform(field1):
for field in field1:
row = tk.Frame()
lab = tk.Label(row, width=15, text=field, anchor='w')
ent = tk.Entry(row)
row.pack(side="top", padx=5, pady=5)
lab.pack(side="left")
ent.pack(side="right")
names.append((field, ent))
return names
if __name__ == ("__init__"):
ents = makeform(field1)
b1 = tk.Button(text='Show',
command=lambda: controller.show_frame(StartPage))
b1.pack(padx=5, pady=5)
app = Yugioh_backEnd()
app.mainloop()

Related

Tkinter switching frame with conditions

I use following code:
Switch between two frames in tkinter
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
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, PageOne):
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()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is the start page", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
self.giris = tk.Entry(self)
self.giris.pack()
self.yazi = tk.Label(self, text="Buraya GİRİLEN VERİ gelecek.")
self.yazi.pack()
button2 = tk.Button(self, text="ae",
command=lambda: [self.alinanmetin(), controller.show_frame("PageOne")])
button2.pack()
def alinanmetin(self):
il = self.giris.get()
self.yazi.config(text="Girdiğiniz il: %s" % il)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
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",
command=lambda: controller.show_frame("StartPage"))
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.geometry("600x400")
app.mainloop()
I want to change my frame according to the value I get from the entry.
if(il =="ali") i want change my frame and
if( il != "ali") i dont want do anything.
I am currently running two functions at the same time.How can i change frame after check value.

having issues with the if statement

With the if-statement that I have put in, it would only display the lose statement even if it is correct.
I'm not sure if the way I wrote the statement is correct.
I'm trying to make it that when pressing start both labels would show a number between 1 to 21.
Also, if it's possible, I want to make it that when the hit button is pressed, a number would be added to the label. For example, pressing hit would add 10 + 5, then display the total.
LOCATED IN CLASS TTY:
import tkinter as tk
k = 10
Q = 10
J = 10
A = 11 or 1
class WINDOW(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Memory") #sets the window title
container = tk.Frame(self)#Name of frame to refer to
container.pack(side="top", fill="both", expand=True)#size of window
container.grid_rowconfigure(0, weight=4)#size of window
container.grid_columnconfigure(0, weight=4)
self.frames = {}
for F in (MainMenu, tty):
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("MainMenu")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class MainMenu(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = 'white')
label = tk.Label(self, text="Memory",font=(15),
borderwidth=5, relief="solid")
label.pack(side="top", fill="y", pady=15, padx=270)
label.pack(fill="both")
button1 = tk.Button(self, text="Start", relief="solid",
borderwidth=5,width=30,
font=(17),command=lambda:
controller.show_frame("tty"))
button1.pack()
button3 = tk.Button(self,
text="Quit",relief="solid",borderwidth=4,width=30,font=(17),command = quit)
button3.place(x="420", y ="50")
button3.pack()
class tty(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = "white")
def win():
if score > deal:
tts = tk.Label(self, text="win", font=(20))
tts.pack()
else:
lose = tk.Label(self, text="lose", font=(10))
lose.pack() #The if statement
deal = tk.Label(self, text="18", font=(18))
deal.pack(side="top", fill="y", pady=15, padx=270)
score = tk.Label(self, text="19", font=(18))
score.pack()
f = tk.Frame(self)
button1 = tk.Button(f,borderwidth=5, text="stand", font=(18),command =
lambda: win())#This is the button that i want to display the label
button1.grid(row=0,column=0)
button2 = tk.Button(f, text="Hit",borderwidth=5, font=(18))
button2.grid(row=0,column=1)
f.pack(side="bottom")
button3 = tk.Button(self, text="Quit", font=(18))
button3.pack(side="right", pady=50)
if __name__ == "__main__":
app = WINDOW()
app.geometry("800x400")
app.mainloop()
if score > deal: is comparing two tkinter label objects rather than the value of score and deal. Try getting the value of the labels and converting them to integers before doing the comparision.
if int(score['text']) > int(deal['text']):
To help with your other questions.
To chose a random number between 1 and 21, use the randint function contained inside python's random module (see code below). I've added a new randomise function which will be called after the page is created to randomly select a value for deal and score.
With the hit button, i've added a new function hit which will take the current score, and add another random value to it.
import tkinter as tk
from random import randint
k = 10
Q = 10
J = 10
A = 11 or 1
class WINDOW(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Memory") #sets the window title
container = tk.Frame(self)#Name of frame to refer to
container.pack(side="top", fill="both", expand=True)#size of window
container.grid_rowconfigure(0, weight=4)#size of window
container.grid_columnconfigure(0, weight=4)
self.frames = {}
for F in (MainMenu, tty):
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("MainMenu")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class MainMenu(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = 'white')
label = tk.Label(self, text="Memory",font=(15),
borderwidth=5, relief="solid")
label.pack(side="top", fill="y", pady=15, padx=270)
label.pack(fill="both")
button1 = tk.Button(self, text="Start", relief="solid",
borderwidth=5,width=30,
font=(17),command=lambda:
controller.show_frame("tty"))
button1.pack()
button3 = tk.Button(self,
text="Quit",relief="solid",borderwidth=4,width=30,font=(17),command = quit)
button3.place(x="420", y ="50")
button3.pack()
class tty(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = "white")
self.deal = tk.Label(self, text="18", font=(18))
self.deal.pack(side="top", fill="y", pady=15, padx=270)
self.score = tk.Label(self, text="19", font=(18))
self.score.pack()
f = tk.Frame(self)
button1 = tk.Button(f,borderwidth=5, text="stand", font=(18),command = self.win)#This is the button that i want to display the label
button1.grid(row=0,column=0)
button2 = tk.Button(f, text="Hit",borderwidth=5, font=(18),command = self.hit)
button2.grid(row=0,column=1)
f.pack(side="bottom")
button3 = tk.Button(self, text="Quit", font=(18))
button3.pack(side="right", pady=50)
self.randomise()
def randomise(self):
self.deal['text'] = str(randint(1,21))
self.score['text'] = str(randint(1,21))
def hit(self):
current_score = int(self.score['text'])
new_score = current_score + randint(1,21)
self.score['text'] = str(new_score)
def win(self):
if int(self.score['text']) > int(self.deal['text']):
tts = tk.Label(self, text="win", font=(20))
tts.pack()
else:
lose = tk.Label(self, text="lose", font=(10))
lose.pack() #The if statement
if __name__ == "__main__":
app = WINDOW()
app.geometry("800x400")
app.mainloop()

want to have my 'back' and 'next' buttons side by side

I have tried grid and place and it will not move the buttons to the place i want them. i don't know if its caused by fill which is stoping it from moving
the buttons are located in class mem
I want to also put the 'Quit' button on the top right of the window
if possible
which is also located in class mem
import tkinter as tk
class WINDOW(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Memory")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=4)
container.grid_columnconfigure(0, weight=4)
self.frames = {}
for F in (MainMenu, mem):
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("MainMenu")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class MainMenu(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = 'white')
label = tk.Label(self, text="Memory",font=(15),
borderwidth=5, relief="solid")
label.pack(side="top", fill="y", pady=15, padx=270)
label.pack(fill="both")
button1 = tk.Button(self, text="Start",relief="solid",borderwidth=5,width=30
,font=(17),command=lambda: controller.show_frame("mem"))
button1.pack()
class mem(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = "white")
label = tk.Label(self, text="9929", font=(18))
label.pack(side="top", fill="y", pady=15, padx=270)
label.pack(fill="x")
button1 = tk.Button(self,relief="solid",borderwidth=5, text="next", font=( 18))
button1.pack(side="bottom")
button2 = tk.Button(self, text="back",borderwidth=5,relief="solid", font=(18))
button2.place()
button2.pack(side="bottom") #HERE are the buttons i want to make side to side
button3 = tk.Button(self, text="Quit", font=(18))
button3.pack(side="right", pady=50)
if __name__ == "__main__":
app = WINDOW()
app.geometry("800x400")
app.mainloop()
The easiest way is to create another Frame to store your next and back buttons, and use grid to align them side by side:
class mem(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = "white")
label = tk.Label(self, text="9929", font=(18))
label.pack(side="top", fill="y", pady=15, padx=270)
#label.pack(fill="x") #you don't need to pack the label twice
f = tk.Frame(self) #create another holder frame
button1 = tk.Button(f,relief="solid",borderwidth=5, text="next", font=(18))
button1.grid(row=0,column=0)
button2 = tk.Button(f, text="back",borderwidth=5,relief="solid", font=(18))
button2.grid(row=0,column=1)
f.pack(side="bottom")
button3 = tk.Button(self, text="Quit", font=(18))
button3.pack(side="right", pady=50)

(tkinter) Why aren't my variables being displayed using labels?

I'm trying to write a program which takes the users information, like their name and stuff, on one page, and then displays these entries on another. I'm using Tkinter and I can't get their entries to display on the other page. Here's the program:
import tkinter as tk
from tkinter import ttk
#PROFILE VARS
FirstName = ('none')
#INITIALIZING
class MegaQuiz(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "THE MEGA POP QUIZ")
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 (ProfilePage, MainPage):
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("ProfilePage")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
#PROFILE PAGE
class ProfilePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
global FirstName
#Profile Title
profile_title = tk.Label(self, text="Create A Profile Yo")
profile_title.grid(column=0, row=2)
#FIRST NAME
Q1_title = tk.Label(self, text="First Name:")
Q1_title.grid(column=0, row=1)
FirstNameEntry = tk.Entry(self)
FirstNameEntry.grid(column=2, row=4)
FirstName = str(FirstNameEntry.get())
#NEXT BUTTON
Button1 = tk.Button(self, text="NEXT",
command = lambda: controller.show_frame("MainPage"))
Button1.grid(column=10, row=10)
#MAIN MENU PAGE
class MainPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
#Play BUTTON
PlayBTN = tk.Button(self, text="PLAY", width=40)
PlayBTN.grid(column=0, row=20, sticky="nesw")
#ProfileDisplay
FirstNameDis = tk.Label(self, text=('FirstName: ' + FirstName))
FirstNameDis.grid(column=0, row=0, sticky="w")
#RUNNING PROGRAM
app = MegaQuiz()
app.mainloop()
The problem is that it displays the "FirstName: ", but doesn't display the variables FirstName, just blankness, help.
The quickest way to fix this is to move your FirstName variable to the MegaQuiz as a class attribute and then use it from there. We can change your NEXT button command to call a class method and then from that method update the FirstName variable and then also set the FirstNameDis label text from that same method.
First move the FirstName variable into your MegaQuiz class by putting this line in the __init__ section.
self.FirstName = 'none'
Then change this:
#NEXT BUTTON
Button1 = tk.Button(self, text="NEXT", command = lambda: controller.show_frame("MainPage"))
To this:
#NEXT BUTTON
Button1 = tk.Button(self, text="NEXT", command=self.next_button)
Button1.grid(column=10, row=10)
def next_button(self):
self.controller.FirstName = self.FirstNameEntry.get()
self.controller.frames["MainPage"].FirstNameDis.config(text='FirstName: ' + self.controller.FirstName)
self.controller.show_frame("MainPage")
In your MainPage change this:
self.FirstNameDis = tk.Label(self, text='FirstName: ' + FirstName)
To this:
self.FirstNameDis = tk.Label(self, text='FirstName: ' + self.controller.FirstName)
That should be all you need to fix this.
I did notice a few PEP8 issues so here is your code rewritten to provide a fix to your problem and also to rewrite some things to better follow the PEP8 guidelines.
Not sure why you are adding () to some of your string variables but it is not needed.
variable and class attribute names should be all lower case with underscores to between words.
You do not need to provide a variable name for everything. If you have a button or a label you know you will not be updating later then you can write them without the variable names.
Code:
import tkinter as tk
class MegaQuiz(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self)
self.title("THE MEGA POP QUIZ")
self.first_name = 'none'
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 (ProfilePage, MainPage):
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("ProfilePage")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class ProfilePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
tk.Label(self, text="Create A Profile Yo").grid(column=0, row=2)
tk.Label(self, text="First Name: ").grid(column=0, row=1)
self.fn_entry = tk.Entry(self)
self.fn_entry.grid(column=2, row=4)
tk.Button(self, text="NEXT", command=self.next_button).grid(column=10, row=10)
def next_button(self):
self.controller.first_name = self.fn_entry.get()
self.controller.frames["MainPage"].fn_dis.config(text='FirstName: {}'.format(self.controller.first_name))
self.controller.show_frame("MainPage")
class MainPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
tk.Button(self, text="PLAY", width=40).grid(column=0, row=20, sticky="nesw")
self.fn_dis = tk.Label(self)
self.fn_dis.grid(column=0, row=0, sticky="w")
app = MegaQuiz()
app.mainloop()

Frame Update Tkinter

So I have read a few posts on here and have tried them all. The current method I have attempted is storing the data in the controller:
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.app_data = {"building": tk.StringVar()}
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, PageOne,PageTwo):
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()
I then have my PageOne receive input from user as to what building they want:
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
#buidling
bldg_label = ttk.Label(self, text="Building Name (ie. ACAD):", font=LARGE_FONT)
bldg_label.grid(row=0, column=0, padx=2, pady = 10)
self.bldg_entry =ttk.Entry(self,width = 6, textvariable = self.controller.app_data["building"])
self.bldg_entry.grid(row=0, column=1, padx=2, pady=10)
button1 = ttk.Button(self, text="next", command = lambda: controller.show_frame(PageTwo))
button1.grid(row = 1, column = 0)
Lastly I want to display the building they typed into the entry box into a label like so:
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
bldg = self.controller.app_data["building"].get()
bldg_label = ttk.Label(self, text = "Building: " + str(bldg), font=LARGE_FONT)
bldg_label.grid(row = 0, column =0)
button1 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.grid(row = 1, column =0)
I know there needs to be some sort of updating but I just can't seem to get the right structure to make this work. The label prints: Building: with nothing in it. My question is how can I get the data that is stored in the dictionary to update the building label in the SecondPage? Any help would be greatly appreciated!

Categories

Resources