Frame Update Tkinter - python

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!

Related

Buttons and Labels Will Not Show Up in Window

The buttons and labels will not show up in my window. If I delete self from the parenthesis (or insert controller instead), the buttons will show up. However, the buttons do not raise the underlying window to the front as it is supposed to. I used a similar code that used pack, and it worked well. I can't seem to find the problem of why using grid won't work. I'm a bit of a beginner to tkinter so perhaps I'm missing something obvious.
import tkinter as tk
LARGE_FONT= ("Verdana", 12)
NORM_FONT= ("Verdana", 10)
SMALL_FONT= ("Verdana", 8)
class mGui(tk.Tk):
def __init__(self, *args, **kargs):
tk.Tk.__init__(self, *args, **kargs)
container = tk.Frame(self)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
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_1 = tk.Label(self, text = "Start Page", font = LARGE_FONT)
label_1.grid(row = 0, column = 0)
button1 = tk.Button(self,text = "Go", command = lambda: controller.show_frame(PageOne))
button1.grid(row = 1, column = 0)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label_1 = tk.Label(self, text = "Page One", font = LARGE_FONT)
label_1.grid(row = 1, column = 4)
button1 = tk.Button(self, text = "Go Back", command = lambda: controller.show_frame(StartPage))
button1.grid(row = 4, column = 1)
app = mGui()
app.mainloop()
You need to add a call to the grid() layout manager for the container Frame as shown:
.
.
.
class mGui(tk.Tk):
def __init__(self, *args, **kargs):
tk.Tk.__init__(self, *args, **kargs)
container = tk.Frame(self)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
container.grid() # ADD THIS.
.
.
.

How to update listbox when I change view in Tkinter?

I need to update listbox when I'm changing view, but I dont know how to do it. On first page I'm adding some items to list and on second it should to show all items in listbox.
# -*- coding: utf-8 -*-
from tkinter import *
tb1 = [["Kofola", "0,5","30"]]
class SeaofBTCapp(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
container = 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):
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(Frame):
def __init__(self, parent, controller):
Frame.__init__(self,parent)
label = Label(self, text="Start Page")
label.pack(pady=10,padx=10)
button = Button(self, text="Visit Page 1",
command=lambda: controller.show_frame(PageOne))
button.pack()
button2 = Button(self, text="add",
command=self.add)
button2.pack()
def add(self):
tb1.append(["Radegast", "0,5","30"])
print(tb1)
class PageOne(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
label = Label(self, text="Page One!!!")
label.pack(pady=10,padx=10)
button1 = Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
self.bill=Listbox(self)
self.bill.pack()
for item in tb1:
co=" ".join(str(x) for x in item)
self.bill.insert(END, co)
app = SeaofBTCapp()
app.mainloop()
In the PageOne class You are reading the list tb1 only once, in __init__(). To get the changes in tb1 to be seen in the listbox you also have to update the listbox with the new altered list.
There is also an issue with the list. As it's defined in the global namespace your app will depend on this. I'd suggest you define it in the SeaofBTCapp() __init__() function and then you can access it through the controller object:
class SeaofBTCapp(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
self.tb1 = [["Kofola", "0,5","30"]]
... etc ...
class StartPage(Frame):
def __init__(self, parent, controller):
self.controller = controller
... etc ...
def add(self):
self.controller.tb1.append(["Radegast", "0,5","30"])
... etc ...
And then add an update() method to the PageOne() class which updates the listbox and calls it from the add() method. I'm calling by way of controller method update_pageone(). See full example below:
from tkinter import *
class SeaofBTCapp(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
self.tb1 = [["Kofola", "0,5","30"]] # Create instance variable tb1
container = 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):
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()
def update_pageone(self):
self.frames[PageOne].update() # Call update on PageOne
class StartPage(Frame):
def __init__(self, parent, controller):
self.controller = controller # Remember the controller
Frame.__init__(self,parent)
label = Label(self, text="Start Page")
label.pack(pady=10,padx=10)
button = Button(self, text="Visit Page 1",
command=lambda: self.controller.show_frame(PageOne))
button.pack()
button2 = Button(self, text="add", command=self.add)
button2.pack()
def add(self):
self.controller.tb1.append(["Radegast", "0,5","30"])
self.controller.update_pageone() # Asking controller for an update
class PageOne(Frame):
def __init__(self, parent, controller):
self.controller = controller # Remember the controller
Frame.__init__(self, parent)
label = Label(self, text="Page One!!!")
label.pack(pady=10,padx=10)
button1 = Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
self.bill = Listbox(self)
self.bill.pack()
for item in controller.tb1:
co = " ".join(str(x) for x in item)
self.bill.insert(END, co)
def update(self):
# Delete all from Listbox bill
self.bill.delete(0, 'end')
# Add revised table into Listbox bill
for item in self.controller.tb1:
co = " ".join(str(x) for x in item)
self.bill.insert(END, co)
app = SeaofBTCapp()
app.mainloop()

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

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()

Notebook with Multiple Frames

I am trying to make a tkinter widow with multiple frames, but also the functions of notebook, like multiple widows. The problem is I am kind of unfamiliar with tkinter and am not sure how to do that. This is my current code, and it doesn't work, and would love to know what I should do to make it work. Again, the dream end result would be that I would have a first widow, which says the test text, and then the 2nd window which has multiple tabs.
from tkinter import ttk
import tkinter as tk
Font= ("Verdana", 8)
LargeFont = ("Verdana", 12)
class App(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, PageOne):
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="Info", font=LargeFont)
label.pack(pady=2,padx=10)
text = tk.Label(self, text="testtestestetetqwegfegeg\ntestwegwegwegweg", font=Font)
text.pack(pady=2,padx=2)
button = tk.Button(self, text="Go to the Card",
command=lambda: controller.show_frame(PageOne))
button.pack(fill="x")
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
nb = ttk.Notebook(ttk.Frame())
nb.grid(row=1, column=0, columnspan = 50, rowspan=49, sticky='nesw')
p1 = (nb)
nb.add(p1, text='test')
label = tk.Label(self, text="", font=LargeFont)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
app = App()
app.mainloop()
The error that I eventually get is that it creates a third frame that is displayed with the test tab. Everything else works.
Thanks for your help
I know exactly what you mean because I'm trying the same. To me
nb = ttk.Notebook(self)
worked.
best
Pkanda
Taubate Brazil

Checkbutton widget in Tkinter (OOP)

The following is an excerpt of a my first python project I am currently working on.
I am able to add the check button into the GUI, but it is practically useless because I can't find out how I can get the value from the checkbutton.
import tkinter as tk
from tkinter import *
class base(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
#tk.Tk.iconbitmap(self, "iconz.ico")
tk.Tk.wm_title(self, "Mandelbrot Renderer")
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, MainPage):
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 MainPage(tk.Frame):
def getcheckvalue(self):
print (self.mvar.get())
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Graph Page!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button2 = ttk.Button(self, text="Re-Render",
command=self.getcheckvalue)
button2.pack()
mvar = IntVar()
self.cbutton = ttk.Checkbutton(self, text="shadow",onvalue=1, offvalue=0, variable=mvar)
self.cbutton.pack()
app = base()
app.geometry ("800x600")
app.mainloop()
mvar = IntVar()
In this line you are creating a local mvar. To access it from outside of your __init__ method, you need to make it class variable by adding self. prefix.
self.mvar = IntVar()
self.cbutton = ttk.Checkbutton(..., variable=self.mvar)

Categories

Resources