How to load another tkinter frame from another class file? Python tkinter - python

import tkinter as tk
from PageTwoFile import PageTwoClass
class SeaofBTCapp(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, PageTwo):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
frame.grid(row=110, column=110, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
def qf(param):
print(param)
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Visit Page 1",
command=lambda: controller.show_frame(PageOne))
button1.pack()
button1 = tk.Button(self, text="Visit Page 2",
command=lambda: controller.show_frame(PageTwo))
button1.pack()
class PageOne(tk.Frame):
def __init__(self, parent,controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Page One", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button2 = tk.Button(self, text="Two",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
app = SeaofBTCapp()
app.mainloop()
In this example I have a class similiar to PageOne but in another file.
class PageTwoClass(tk.Frame):
def __init__(self, parent,controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Page Two", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button2 = tk.Button(self, text="Page One",
command=lambda: controller.show_frame(PageOne))
button2.pack()
I can run it fine, but when I go to PageTwo I can't go back to PageOne, I get:
NameError: name 'PageOne' is not defined
I assume that is going in to PageTwoFile and does not know how to come back. How to make it read everything?
I am working on a banking system and I have another files(customer,accounts) which are imported in the main file. If I want to change frames for when they are accessed I need them to go back...

The solution is to use the name of the class rather than the actual class itself, so that the different classes don't have to import each other.
A better version of the code you started from, with the modification to use the page name rather than the page class, is here: https://stackoverflow.com/a/7557028/7432

Related

How to reload the frame in tkinter everytime switching the frame?

I am using something similar to bellow code to navigation between windows in my tkinter desktop app. However the problem in bellow approach is that since all the frames are loaded at once, even though when i switch windows, it still returns the previous page. however in my use case i am loading metadata from database(picklist values) so i want to reload each frame whenever i switch the windows? How do i modify this code in such a way that every time i switch to a different frame, it reload the frame again.
import tkinter as tk
LARGE_FONT= ("Verdana", 12)
class SeaofBTCapp(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, 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()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button = tk.Button(self, text="Visit Page 1",
command=lambda: controller.show_frame(PageOne))
button.pack()
button2 = tk.Button(self, text="Visit Page 2",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page One!!!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button2 = tk.Button(self, text="Page Two",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page Two!!!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button2 = tk.Button(self, text="Page One",
command=lambda: controller.show_frame(PageOne))
button2.pack()
app = SeaofBTCapp()
app.mainloop()
If you want to recreate each page when it is shown, you have complete control in the show_frame method to do exactly that.
class SeaofBTCapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.container = tk.Frame(self)
self.container.pack(fill="both", expand=True)
self.current_frame = None
self.show_frame(StartPage)
def show_frame(self, new_frame_class):
if self.current_frame:
self.current_frame.destroy()
self.current_frame = new_frame_class(self.container, controller=self)
self.current_frame.pack(fill="both", expand=True)

Displaying an image in only its own frame with tkinter

I'm trying to create a simple GUI with tkinter with buttons and images. I have a startpage with an image and buttons that take you to other pages(frames). The problem is that the image in my startpage persists and displays in the other frames.
The code:
import tkinter as tk
LARGE_FONT = ("Verdana", 12)
class SeaofBTCapp(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, PageTwo):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.geometry("800x480")
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="Start Page", font=LARGE_FONT)
label.pack(pady=10, padx=10)
#canvas1 = tk.Canvas(width=600, height=300, bg="gray")
#self.img = tk.PhotoImage(file="mario.png")
#canvas1.create_image(20, 20, image=self.img)
#canvas1.pack()
photo = tk.PhotoImage(file="mario.png")
labelimg = tk.Label(image=photo)
labelimg.image = photo # keep a reference!
labelimg.pack()
button = tk.Button(self, text="Visit Page 1",
command=lambda: controller.show_frame(PageOne))
button.pack()
button2 = tk.Button(self, text="Visit Page 2",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page One!!!", font=LARGE_FONT)
label.pack(pady=10, padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page Two!!!", font=LARGE_FONT)
label.pack(pady=10, padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button2 = tk.Button(self, text="Page One",
command=lambda: controller.show_frame(PageOne))
button2.pack()
app = SeaofBTCapp()
app.mainloop()
The issue is that you have not specified labelimg's parent therefore, by default it is the main window. As a consequence, your label is packed below your container and therefore is always visible.
Changing
labelimg = tk.Label(image=photo)
into
labelimg = tk.Label(self, image=photo)
in the class StartPage should solve your problem.

How to change page through my menu bar methods in tkinter?

Basically what I'm trying to figure out is, how do I make my menu bar "buttons" change the page?
I've already made the dropdown menu, and the classes with each page. The thing is it works if I create a separate button to change the page, but not when i'm trying to do it through the menu bar?
every tutorial I find is through the buttons, and only the buttons..
I am using python 3.6, with tkinter.
import tkinter as tk
class MyApp(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 = {}
menu = tk.Menu(container)
betting = tk.Menu(menu, tearoff=0)
menu.add_cascade(menu=betting, label="Pages")
betting.add_command(label="PageOne",
command=lambda: controller.show_frame(PageOne))
betting.add_command(label="PageTwo",
command=lambda: controller.show_frame(PageTwo))
tk.Tk.config(self, menu=menu)
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()
class Startpage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Home")
label.pack(pady=10, padx=10)
button1 = tk.Button(self, text="page 1",
command=lambda: controller.show_frame(PageOne))
button1.pack()
button2 = tk.Button(self, text="Page Two",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
# ***** PAGES *****
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Back to Home")
label.pack(pady=10, padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(Startpage))
button1.pack()
button2 = tk.Button(self, text="Page Two",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page Two")
label.pack(pady=10, padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(Startpage))
button1.pack()
button2 = tk.Button(self, text="Page One",
command=lambda: controller.show_frame(PageOne))
button2.pack()
app = MyApp()
app.geometry("1200x600")
app.mainloop()
Now I know, I haven't parsed the "controller & parent", right now, but I've tried and tried, and nothing works for me...
The controller is MyApp. Within the definition of MyApp that makes controller be self. Thus, you need to call self.show_frame rather than controller.show_frame.
betting.add_command(label="PageOne",
command=lambda: self.show_frame(PageOne))
betting.add_command(label="PageTwo",
command=lambda: self.show_frame(PageTwo))

Starting another script using a button in tkinter

I am trying to run another script within a script using a button in tkinter
I have tried two methods one being
import os
class SeaofBTCapp(tk.Tk):
#initilization
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Battery Life Calculator")
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, PageThree):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
#raise each page to the front
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
def helloCallBack():
os.system('python test2.py')
#the start page
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = ttk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button = ttk.Button(self, text="Visit Page 1",command=lambda:controller.show_frame(PageOne))
button.pack()
button1 = ttk.Button(self, text="Visit Page 2",command=lambda:controller.show_frame(PageTwo))
button1.pack()
button2 = ttk.Button(self, text="Visit Graph page",command=lambda:controller.show_frame(PageThree))
button2.pack()
button3 = ttk.Button(self, text="execute test",command=lambda:controller.helloCallBack)
button3.pack()
No errors are given but when I hit execute nothing happens
The other method i tried was to
import test2
but it runs the script automatically and it prints "i am a test"
I should note the script i am trying to call is simply a test and just prints "i am a test"
any help is appreciated!
thanks
****edit****
import tkinter as tk
from tkinter import ttk
import test2
LARGE_FONT= ("Verdana", 12)
class SeaofBTCapp(tk.Tk):
#initilization
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Battery Life Calculator")
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, PageThree):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
#raise each page to the front
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
#the start page
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = ttk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button = ttk.Button(self, text="Visit Page 1",command=lambda:controller.show_frame(PageOne))
button.pack()
button1 = ttk.Button(self, text="Visit Page 2",command=lambda:controller.show_frame(PageTwo))
button1.pack()
button2 = ttk.Button(self, text="Visit Graph page",command=lambda:controller.show_frame(PageThree))
button2.pack()
button3 = ttk.Button(self, text="execute test",command=test2.main)
button3.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = ttk.Label(self, text="Page One", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Back to start page",command=lambda:controller.show_frame(StartPage))
button1.pack()
button1 = ttk.Button(self, text="Visit Page 2",command=lambda:controller.show_frame(PageTwo))
button1.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = ttk.Label(self, text="Page One", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Back to Start Page",command=lambda:controller.show_frame(StartPage))
button1.pack()
button1 = ttk.Button(self, text="Back to Page One",command=lambda:controller.show_frame(PageOne))
button1.pack()
class PageThree(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = ttk.Label(self, text="Graph Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Back to Start Page",command=lambda:controller.show_frame(StartPage))
button1.pack()
app = SeaofBTCapp()
app.mainloop()
test2.p is as follows
def main():
if __name__ == "__main__":
print("Executing as main program")
print("Value of __name__ is: ", __name__)
main()
Your first method is not recommended for that. If you have another python script you should definitely import it.
About the second method:
My guess is that the script test2.py is written without
if __name__ == "__main__":
main()
And that's why it shoot you message when you import it.

Navigating between multiple Tkinter GUI frames

I found some code online to create a tkinter GUI with multiple frames. I tried to modify the code to include a frame with navigation buttons to be displayed on each frame, rather than repeating the code each time. I keep getting error messages and cannot work out how to connect the navigation buttons to the corresponding frame.
This is the code for the closest I have got:
import Tkinter as tk
LARGE_FONT= ("Verdana", 12)
class SeaofBTCapp(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, 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()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button = tk.Button(self, text="Visit Page 1",
command=lambda: controller.show_frame(PageOne))
button.pack()
button2 = tk.Button(self, text="Visit Page 2",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page One!!!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button2 = tk.Button(self, text="Page Two",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
btns = MainButtonFrame(self,SeaofBTCapp)
btns.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page Two!!!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button2 = tk.Button(self, text="Page One",
command=lambda: controller.show_frame(PageOne))
button2.pack()
btns = MainButtonFrame(self,SeaofBTCapp)
btns.pack()
class MainButtonFrame(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
Pages = [StartPage,PageOne,PageTwo ]
for button in Pages:
NewButton = tk.Button(self, text=str(button),
command=lambda: controller.show_frame(button))
NewButton.pack()
app = SeaofBTCapp()
app.mainloop()
and the error message I got is:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1536, in __call__
return self.func(*args)
File "<ipython-input-13-dcc5fdbf1581>", line 103, in <lambda>
command=lambda: controller.show_frame(button))
TypeError: unbound method show_frame() must be called with SeaofBTCapp
instance as first argument (got classobj instance instead)
Any help would be much appreciated in suggesting what I am doing wrong in the button commands. If I can get this working I will use it as a framework to build a bigger GUI on. Thanks!
The initializer of MainButtonFrame needs a parent and a controller. The controller must be the instance of the main app, not the class. Change how you create MainButtonFrame to be this:
btns = MainButtonFrame(self,controller)

Categories

Resources