Python tkinter code - frames with imported image buttons - python

Currently the program opens up an empty blank window when trying to import images as buttons. Without trying to import the image as buttons, the code works fine however. Can anyone help fix this code up or point me in the right direction?
from tkinter import*
root = Tk()
class app(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, SignIn, SignUp):
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)
img1 = PhotoImage(file="signinbtn.png")
button = Button(self, image=img1,
command=lambda: controller.show_frame(SignIn))
button.pack()
img2 = PhotoImage(file="signupbtn.png")
button2 = Button(self, image=img2, text="Sign Up",
command=lambda: controller.show_frame(SignUp))
button2.pack()
class SignIn(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
label = Label(self, text="Sign In")
label.pack(pady=10,padx=10)
button1 = Button(self, text="Back to Start Page",
command=lambda: controller.show_frame(StartPage))
button1.pack()
class SignUp(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
label = Label(self, text="Sign Up")
label.pack(pady=10,padx=10)
button1 = Button(self, text="Back to Start Page",
command=lambda: controller.show_frame(StartPage))
button1.pack()
root.mainloop()

The empty window is created by the second code line:
root = Tk()
Apart from this line you have just class definitions. As you never instantiate any of the classes no code from any class is run.

Related

How can I refresh/reinitialize a class with the values gotten from another class?

So the question title pretty much sums it up. I apologise in advance if I have too much information as I don't know exactly where the problem arises but the issue is in the transition between class StartPage and class PageOne.I basically want to get the text from first_button (I will add more of these later) and grab data from a file which has a name matching to the button text. This data will then be added in the for-loop in PageOne. However, it seems like PageOne is at its initial state despite the function transition()
from tempSimulator import lasdata
import tkinter as tk
class SalladBar:
def __init__(self,master):
self.master=master
master.geometry("1300x700")
container = tk.Frame(self.master)
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 update_frame(self, page):
frame = self.frames[page]
frame.update()
def show_frame(self, page):
frame = self.frames[page]
frame.tkraise()
class variables:
data1=[]
data2=[]
class startPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
f1 = tk.Frame(self, width="1300", height="200", bd=6, relief="raise")
f1.pack()
label = tk.Label(f1, text="xxxx")
label.pack(pady=10, padx=10)
#Add more buttons
first_button= tk.Button(f1, text="Source",
command=lambda: self.transition(controller,first_button.cget("text")))
first_button.pack()
def transition(self,controller,source):
data1,data2=lasdata(source)
variables.data1=data1
variables.data2=data2
controller.update_frame(PageOne) #I thought this would do the trick
controller.show_frame(PageOne)
class PageOne(tk.Frame):
print("PageOne initialised")
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
f1=tk.Frame(self, width="1300", height="200", bd=6, relief="raise")
f1.pack()
label = tk.Label(f1, text="Title2")
label.pack(pady=10, padx=10)
for d in variables.data1:
sld_label= tk.Label(f1, text= d.givename() + "\n" + d.givedet())
sld_label.pack()
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(startPage))
button1.pack()
root = tk.Tk()
app = SalladBar(root)
root.mainloop()
You need to move the data adding code to a separate method if you want to call it later. Things that are in the __init__ method are executed when the instance is created, and never again.
class PageOne(tk.Frame):
print("PageOne initialised")
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.f1=tk.Frame(self, width="1300", height="200", bd=6, relief="raise")
self.f1.pack()
label = tk.Label(self.f1, text="Title2")
label.pack(pady=10, padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(startPage))
button1.pack()
def add_data(self):
for d in variables.data1:
sld_label= tk.Label(self.f1, text= d.givename() + "\n" + d.givedet())
sld_label.pack()
Once you have done that you can call that method from another class like this:
def transition(self,controller,source):
data1,data2=lasdata(source)
variables.data1=data1
variables.data2=data2
controller.frames[PageOne].add_data() # update the other page
controller.show_frame(PageOne)

How to swap between pages / windows in Tkinter

I have tried googling and everyone seems to have structured their code completely differently. I understand the base level tkinter, however I do not understand how people are using classes and def's to swap pages. How can I swap from my main window to my second one? (and not open the second one after the main is closed)
import tkinter as tk
main = tk.Tk()
main.title("Main Program")
firstlabel = tk.Label(main, text="This is a program!")
firstlabel.pack()
main.mainloop()
second = tk.Tk()
second.title("Second Program")
firstlabel = tk.Label(second, text="This is another program!")
firstlabel.pack()
second.mainloop()
EDIT: (solution)
import tkinter as tk
class Application(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=("Consolas", 30))
label.pack(pady=10,padx=10)
button = tk.Button(self, text="Visit Page 1", command=lambda: controller.show_frame(PageOne))
button.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page One!!!", font=("Consolas", 30))
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home", command=lambda: controller.show_frame(StartPage))
button1.pack()
app = Application()
app.mainloop()
One way do this is by clearing everything (every widget), with this function:
def clear(app):
# Delete everything else in app
widget_list = app.winfo_children()
for item in widget_list:
if item.winfo_children():
widget_list.extend(item.winfo_children())
for item in widget_list:
item.pack_forget()
And then puting in the new window you want to swap to (every window should hav its own frame to make it simpler).
Try this::::
tk.Toplevel(main)

Two windows appear on my tkinter app

I am quite new to python and tkinter and I was trying to open iamges to use them as icons on my program, so I found I have to use tk.Toplevel instead of tk.Tk. However, when I do this, the application opens two windows,the one where everything is programmed and a blank one.
Here is the full code in case anyone could help:
import tkinter as tk
from tkinter import ttk
from tkinter import PhotoImage
from PIL import Image, ImageTk
Large_Font = ("Times", 20)
class RobProject(tk.Toplevel):
def __init__(self):
tk.Toplevel.__init__(self)
tk.Tk.wm_title(self, "Com-Bot Control")
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 (MenuPage, PageOne, PageTwo, PageThree):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="NEWS")
self.show_frame(MenuPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class MenuPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text = "Menú", font=Large_Font)
label.pack(pady=10, padx=10)
RCB = ttk.Button(self, text="Control Remoto",
command= lambda: controller.show_frame(PageOne))
RCB.pack()
EOB = ttk.Button(self, text="EvitaObstáculos",
command= lambda: controller.show_frame(PageTwo))
EOB.pack()
SLB = ttk.Button(self, text="Siguelíneas",
command= lambda: controller.show_frame(PageThree))
SLB.pack()
img = Image.open("play-button.png")
photo = ImageTk.PhotoImage(img)
Show_Im = tk.Button(self, image=photo)
Show_Im.image = photo
Show_Im.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text = "Control Remoto", font=Large_Font)
label.pack(pady=10, padx=10)
Back_B1 = ttk.Button(self, text="Atrás",
command= lambda: controller.show_frame(MenuPage))
Back_B1.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text = "Evitaobstáculos", font=Large_Font)
label.pack(pady=10, padx=10)
Back_B2 = ttk.Button(self, text="Atrás",
command= lambda: controller.show_frame(MenuPage))
Back_B2.pack()
class PageThree(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text = "Siguelíneas", font=Large_Font)
label.pack(pady=10, padx=10)
Back_B3 = ttk.Button(self, text="Atrás",
command= lambda: controller.show_frame(MenuPage))
Back_B3.pack()
app = RobProject()
app.mainloop()
Thank you in advance!
You do not need Topelevel() to use images.
Not sure where you got that info but it is not accurate.
Toplevel() is specifically to create new windows outside of the root window in tkinter.
What is happening is when you call tk.Toplevel() tkinter is creating an instance of Tk() in order to run Toplevel(). This is where the blank screen is coming from. The blank screen is actually the root window without anything in it.
To fix your problem Change:
class RobProject(tk.Toplevel):
def __init__(self):
tk.Toplevel.__init__(self)
To:
class RobProject(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)

Tkinter GUI frames - autoloading frame using 'after'?

I've been experimenting with some code I found here which lets you navigate between multiple tkinter GUI frames:
Navigating between multiple Tkinter GUI frames
And I'm trying to see if I can autoload a specific frame after a certain amount of time passes, (similar to a sleep screen / screensaver).
I've used the .after method and beginning right after frame.tkraise(). It calls a new class called Autoload, which is currently just a copy of the main App Class SeaofBTCapp.
It works, but the obvious problem with this is that it's popping out the frame into a new window because it's calling this again:
tk.Tk.__init__(self, *args, **kwargs)
I'm a total newb, so I apologize for asking a very obvious question, but what is the best way to keep it from popping out? If I copy the code from one of the Frame classes, it tells me that __init__ is not getting enough arguments. I have tried various (obvious) things, but having trouble wrapping my head around this because it ultimately would have to be a passive function operating in the back of the main app, without hindering other functionality (calling new frames). I'm probably just overthinking this and have missed a very simple and elegant solution. Any thoughts?
Here's the full code, thanks for help!
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()
frame.after(2000, Autoload) #####
class Autoload(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()
frame.after(2000, Autoload) #####
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()

Python tkinter callback

I have a container with a set of frames, that provide me with two pages (main page and an info page.) Buttons are used to navigate the pages.
All is working.
I have defined a function to remove folders on the OS. (shutil.rmtree) This function should be called by my button 2 on the main page, but it falls over and is not working.
import tkinter as tk
import shutil
from tkinter import *
TITLE_FONT = ("Helvetica", 18, "bold")
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# 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 (MainPage, InfoPage,):
frame = F(container, self)
self.frames[F] = 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(MainPage)
def show_frame(self, c):
'''Show a frame for the given class'''
frame = self.frames[c]
frame.tkraise()
class MainPage(tk.Frame):
def callback(self):
shutil.rmtree('C:\Test', ignore_errors=False)
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
photo = PhotoImage(file='C:\Logo.gif')
label = Label(self, image=photo)
label.Image = photo
label.pack(side=TOP)
button1 = tk.Button(self, text="Info!",
command=lambda: controller.show_frame(InfoPage))
button1.pack(side=LEFT, padx=5, pady=5)
button2 = tk.Button(self, text="Clean!", command=callback)
button2.pack(side=RIGHT, padx=5, pady=5)
class InfoPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Info Page", font=TITLE_FONT)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Back",
command=lambda: controller.show_frame(MainPage))
button.pack()
if __name__ == "__main__":
app = App()
app.mainloop()

Categories