How to prevent multiple windows from popping up in tkinter? - python

import tkinter as tk
from tkinter import *
from tkinter import ttk
LARGE_FONT = ("Verdana", 12)
class pages(tk.Tk):
#starts us off in the login page
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "ScanNET")
tk.Tk.wm_minsize(self, 800, 800)
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 (loginpage, GUI):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky=N+E+S+W)
self.show_frame(loginpage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class loginpage(tk.Frame):
#login page content
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
loginlabel = tk.Label(self, text="login page", font=LARGE_FONT)
loginlabel.pack(padx=10, pady=10)
#button moves you to gui
loginbutton1 = tk.Button(self, text= "Go to GUI", command=lambda: controller.show_frame(GUI))
loginbutton1.pack()
class GUI(tk.Frame):
def __init__(self, parent, controller):
#all widths and heights aren't official, most likely change
tk.Frame.__init__(self, parent)
self.root = tk.Tk()
#the tabs
my_notebook = ttk.Notebook(self.root)
my_notebook.pack()
devicestab = Frame(my_notebook, width=800, height=600)
reportstab = Frame(my_notebook, width=800, height=600)
devicestab.pack(fill=BOTH, expand=1)
reportstab.pack(fill=BOTH, expand=1)
my_notebook.add(devicestab, text="Devices")
my_notebook.add(reportstab, text="Reports")
#contents for devices tab
devicesleft = LabelFrame(devicestab, text="Devices found: ", padx=5, pady=5, width=500, height=600)
devicesleft.grid(row=0, column=0)
devicesright = LabelFrame(devicestab, text="Activity Feed: ", padx=5, pady=5, width=300 , height=600)
devicesright.grid(row=0, column=1)
#contents for reports tab
reportsleft = LabelFrame(reportstab, text="Report Summaries: ", padx=5, pady=5, width=400 , height=600)
reportsleft.grid(row=0, column=0)
reportsright= LabelFrame(reportstab, text="Charts and Diagrams: ", padx=5, pady=5, width=400 , height=600)
reportsright.grid(row=0, column=1)
app = pages()
app.mainloop()
When I run this, both the loginpage and GUI windows open. Correct me if I'm wrong, but I think the problem is probably around the
tk.Frame.__init__(self, parent)
self.root = tk.Tk()
my_notebook = ttk.Notebook(self.root)
part in the GUI class. I've searched everywhere and I can't seem to find a way to have a first page as a login page which will move to a second page that has tabs using notebook. I feel as if something else has to be in the ttk.Notebook() part, and perhaps remove self.root = tk.Tk() after. I'd love to hear what y'all think.

I am assuming you want the notebook in the same widget of the rest, so you should not use tk.Tk() and then you place the notebook in the parent which is already your root. Check the code in the end of my answer. Also, since there was a lot of problems with your code I made some changes and comments that will help you to write better codes in tkinter. Please read it carefully. You may also want to study the effbot web page.
import tkinter as tk
# from tkinter import * # just don't do this
from tkinter import ttk
LARGE_FONT = ("Verdana", 12)
# class pages(tk.Tk):
class Pages(tk.Tk): # class names should start with upper case
#starts us off in the login page
# def __init__(self, *args, **kwargs):
def __init__(self):
# tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.__init__(self)
# tk.Tk.wm_title(self, "ScanNET")
self.winfo_toplevel().title("ScanNET")
# tk.Tk.wm_minsize(self, 800, 800)
self.wm_minsize(800, 800) # since you defined tk.Tk as pages parent you can call Tk methods directly
container = tk.Frame(self)
# container.pack(side=TOP, fill=BOTH, expand=True)
# container.grid_rowconfigure(0, weight=1)
# container.grid_columnconfigure(0, weight=1)
container.grid(row=0, column = 0) # don't use pack if you want to use grid
self.frames = {}
for F in (loginpage, GUI):
frame = F(container, self)
self.frames[F] = frame
# frame.grid(row=0, column=0, sticky=N+E+S+W)
frame.grid(row=0, column=0, sticky='NESW') #since we are not importing all we are not importing tk.W but you can use string instead
self.show_frame(loginpage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class loginpage(tk.Frame):
#login page content
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
loginlabel = tk.Label(self, text="login page", font=LARGE_FONT)
loginlabel.pack(padx=10, pady=10)
#button moves you to gui
loginbutton1 = tk.Button(self, text= "Go to GUI", command=lambda: controller.show_frame(GUI))
loginbutton1.pack()
class GUI(tk.Frame):
def __init__(self, parent, controller):
#all widths and heights aren't official, most likely change
tk.Frame.__init__(self, parent)
# self.root = tk.Tk() # don't create new Tk objects, you just need one. The others should be Toplevel objects
### self.root = tk.Toplevel() ### this would be the correct way of creating a new window but you don't want to do that here your root is your parent
#the tabs
# my_notebook = ttk.Notebook(self.root)
my_notebook = ttk.Notebook(self) # this is how you place the notebook in the Frame widget and not in a new one
# my_notebook.pack()
my_notebook.grid() # we are now using grid so it will not accept pack anymore
# devicestab = Frame(my_notebook, width=800, height=600)
devicestab = tk.Frame(my_notebook, width=800, height=600) # again, since we are not importing al we have to use tk. before tkinter methods
# reportstab = Frame(my_notebook, width=800, height=600)
reportstab = tk.Frame(my_notebook, width=800, height=600)
# devicestab.pack(fill=BOTH, expand=1)
devicestab.pack(fill="both", expand=1) # instead of tk.BOTH we can use "both"
reportstab.pack(fill="both", expand=1)
my_notebook.add(devicestab, text="Devices")
my_notebook.add(reportstab, text="Reports")
#contents for devices tab
devicesleft = tk.LabelFrame(devicestab, text="Devices found: ", padx=5, pady=5, width=500, height=600)
devicesleft.grid(row=0, column=0)
devicesright = tk.LabelFrame(devicestab, text="Activity Feed: ", padx=5, pady=5, width=300 , height=600)
devicesright.grid(row=0, column=1)
#contents for reports tab
reportsleft = tk.LabelFrame(reportstab, text="Report Summaries: ", padx=5, pady=5, width=400 , height=600)
reportsleft.grid(row=0, column=0)
reportsright= tk.LabelFrame(reportstab, text="Charts and Diagrams: ", padx=5, pady=5, width=400 , height=600)
reportsright.grid(row=0, column=1)
app = Pages()
app.mainloop()

Related

Frame inside A OOP Tkinter Frame

Right so I am trying to put a frame into the waiter page to split it into different frames
like this design but nothings working.
This is the design:
I've tried to create a basic Frame inside but it doesn't appear.
The Frame that I created doesnt throw an error however it might be in a different position, So I attempted to move it but it didn't change anything and just didn't display it on the WaiterPage.
Note There is no validation for the login so just click login after choosing WaiterPage.
import tkinter as tk
from tkinter import SUNKEN, Label, ttk
from tkinter import IntVar
from tkinter.constants import BOTH, BOTTOM, CENTER, GROOVE, LEFT, RIGHT
from typing import Container
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self,*args,**kwargs)
self.bg = tk.PhotoImage(file="D:/talha\Documents\Projects For Portfolio\Some Fun\CourseWork\Testbg.png")
container = tk.Frame(self)
self.geometry("800x500")
self.resizable(False,False)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for page in (ManagerPage, WaiterPage, Login):
frame = page(container,self)
self.frames[page] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(page)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class WaiterPage(tk.Frame):
def __init__(self, parent, controller):
MainFrame = tk.Frame.__init__(self, parent)
RightFrame = tk.Frame(MainFrame, background='blue')
class ManagerPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tk.Label(self, text="Manager Page:").pack()
LeftFrame = tk.Frame(self)
LeftFrame.pack(side=LEFT)
CurrentTables = tk.Listbox(LeftFrame, width=70,height=33).pack(side=LEFT,fill=BOTH)
AddTable = ttk.Button(self, text="Add Table").place(width=160,height=37,relx=0.65, rely=0.5, anchor=CENTER)
AddBooking = ttk.Button(self, text="Add Booking").place(width=160,height=37,relx=0.875, rely=0.5, anchor=CENTER)
ViewBooking = ttk.Button(self, text="View Booking").place(width=160, height=37,relx=0.65, rely=0.65, anchor=CENTER)
Collection = ttk.Button(self, text="Collection").place(width=160,height=37,relx=0.875, rely=0.65, anchor=CENTER)
Inventory = ttk.Button(self, text="View Inventory").place(width=160,height=37,relx=0.75, rely=0.8, anchor=CENTER)
Exit = ttk.Button(self, text="Exit").place(width=160,height=37,relx=0.75, rely=0.9, anchor=CENTER)
class Login(tk.Frame):
def __init__(self, parent, controller):
def CallBack():
if ManagerValue.get() == 1:
WaiterCheck.configure(state='disabled')
if WaiterValue.get() == 1:
ManagerCheck.configure(state='disabled')
if ManagerValue.get() == 0:
WaiterCheck.configure(state='normal')
if WaiterValue.get() == 0:
ManagerCheck.configure(state='normal')
def CheckPage():
if ManagerValue.get() == 1:
self.controller.show_frame(ManagerPage)
if WaiterValue.get() == 1:
self.controller.show_frame(WaiterPage)
tk.Frame.__init__(self,parent)
self.controller = controller
label_bkgr = tk.Label(self, image=self.controller.bg)
label_bkgr.place(relx=0.5, rely=0.5, anchor=CENTER)
tk.Label(self, text="Username: ",font=("Segoe UI", 12),bg='#59C8E3').place(relx=0.3, rely=0.35, anchor=CENTER)
tk.Label(self, text="Password: ",font=("Segoe UI", 12),bg='#59C8E3').place(relx=0.3, rely=0.45, anchor=CENTER)
ManagerValue = IntVar()
WaiterValue = IntVar()
ManagerCheck = tk.Checkbutton(self, text="Manager",variable=ManagerValue,command=CallBack,font=("Segoe UI", 12),bg='#59C8E3',activebackground='#59C8E3')
ManagerCheck.place(relx=0.43, rely=0.535, anchor=CENTER)
WaiterCheck = tk.Checkbutton(self, text="Waiter",variable=WaiterValue,command=CallBack,font=("Segoe UI", 12),bg='#59C8E3',activebackground='#59C8E3')
WaiterCheck.place(relx=0.59, rely=0.535, anchor=CENTER)
UserEntry = ttk.Entry(self)
UserEntry.place(width=160,
height=37,relx=0.5, rely=0.35, anchor=CENTER)
PassEntry = ttk.Entry(self)
PassEntry.configure(show="*")
PassEntry.place(width=160,
height=37,relx=0.5, rely=0.45, anchor=CENTER)
Submit = ttk.Button(self, text="Submit",command=CheckPage)
Submit.place(width=160,
height=37,relx=0.5, rely=0.6, anchor=CENTER)
app = App()
app.mainloop()
The first problem is that you never call pack or grid on RightFrame, so it will never appear.
The second problem is that RightFrame needs to be a child of self because MainFrame is None.
class WaiterPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
RightFrame = tk.Frame(self, background='blue')
RightFrame.pack(fill="both", expand=True)
I don't know if pack(fill="both", expand=True) are the right options, but the point is you have to call pack or grid or place on the frame in order for it to be visible.

How to keep a constant layout in multiple windows Tkinter program?

I am working on a Python Tkinter application which is expected to have multiple windows. At the same time, I would like to keep certain layout (background image, Top/bottom labels) constant. I have tried to set the background image (b_image) and top left label (topleft_label ) but it's not showing up. Can someone look at this snippet and advise how to achieve this?
import tkinter as tk
LARGE_FONT= ("Verdana", 12)
HEIGHT = 768
WIDTH = 1024
class MainApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title("Sales System") # set the title of the main window
self.geometry("%dx%d+0+0" % (WIDTH, HEIGHT)) # set size of the main window to 300x300 pixels
container = tk.Frame(self)
b_image = tk.PhotoImage(file='background.png')
b_label = tk.Label(container, image=b_image)
b_label.place(relwidth=1, relheight=1)
topleft_label = tk.Label(container, bg='black', fg='white', text="Welcome - Login Screen", justify='left', anchor="w", font="Verdana 12")
topleft_label.place(relwidth=0.5, relheight=0.05, relx=0.25, rely=0, anchor='n')
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
frame = StartPage(container, self)
self.frames[StartPage] = 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)
app = MainApp()
app.mainloop()
The approach
The best way of going about this is most likely be to make a base_frame class, which contains the image and the topleft_label, "Welcome - Login Screen". This means the StartPage object can inherit the background image from the base_frame class.
The Code
import tkinter as tk
LARGE_FONT= ("Verdana", 12)
HEIGHT = 768
WIDTH = 1366
class MainApp():
def __init__(self, master):
self.master = master
self.master.title("Sales System")
self.master.geometry("%dx%d+0+0" % (WIDTH, HEIGHT))
self.frames = {}
start_page = StartPage(master)
self.frames[StartPage] = start_page
start_page.grid(row=0, column=0, sticky="nsew")
self.master.grid_rowconfigure(0, weight=1)
self.master.grid_columnconfigure(0, weight=1)
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class base_frame(tk.Frame):
def __init__(self, master, *args, **kwargs):
tk.Frame.__init__(master, *args, **kwargs)
b_image = tk.PhotoImage(file='background.png')
b_label = tk.Label(self, image=b_image)
b_label.image = b_image
b_label.place(x=0, y=0, relwidth=1, relheight=1)
topleft_label = tk.Label(self, bg='black', fg='white', text="Welcome - Login Screen", justify='left', anchor="w", font="Verdana 12")
topleft_label.place(relwidth=0.5, relheight=0.05, relx=0.25, rely=0, anchor='n')
class StartPage(base_frame):
def __init__(self, parent):
super().__init__(self, parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
def main():
root = tk.Tk() # MainApp()
main_app = MainApp(root)
root.mainloop()
if __name__ == '__main__':
main()
The Breakdown
Starting the Code
The piece of code that makes this class system run is like so:
def main():
root = tk.Tk() # MainApp()
main_app = MainApp(root)
root.mainloop()
if __name__ == '__main__':
main()
The line if __name__ == '__main__':, in English, roughly translates too: If the program is run and not imported. So, if the program is run and not imported, run the main function.
root = tk.Tk() simply creates a Tk window inside of the root variable.
main_app = MainApp(root) initializes the main_app object with its master being the root variable
root.mainloop() starts the tkinter loop.
The MainApp Class
The MainApp Class starts by setting its title to "Sales System" and resetting the geometry to the values defined in HEIGHT & WIDTH:
self.master = master
self.master.title("Sales System")
self.master.geometry("%dx%d+0+0" % (WIDTH, HEIGHT))
Then the self.frames dictionary & the start_page is initialized and the start_page is placed in self.frames:
self.frames = {}
start_page = StartPage(master)
self.frames[StartPage] = start_page
The start_page is then set to fill the whole of the window:
start_page.grid(row=0, column=0, sticky="nsew")
self.master.grid_rowconfigure(0, weight=1)
self.master.grid_columnconfigure(0, weight=1)
We then show the first page:
self.show_frame(StartPage)
The show_frame function is then created
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
The base_frame Class
The first 3 lines creates a class which takes values the same as a tk.Frame object does, with args and key word args passed through:
class base_frame(tk.Frame):
def __init__(self, master, *args, **kwargs):
tk.Frame.__init__(master, *args, **kwargs)
Then the image label is created:
b_image = tk.PhotoImage(file='background.png')
b_label = tk.Label(self, image=b_image)
b_label.image = b_image
b_label.place(x=0, y=0, relwidth=1, relheight=1)
The b_label.image = b_image line is used to make sure the image is shown by the label (this is required when loading from within a function).
We then create the default topleft_label:
topleft_label = tk.Label(self, bg='black', fg='white', text="Welcome - Login Screen", justify='left', anchor="w", font="Verdana 12")
topleft_label.place(relwidth=0.5, relheight=0.05, relx=0.25, rely=0, anchor='n')
You may wish to update this code for these labels to be changed in the future, to do this simply replace topleft_label with self.topleft_label and b_label with self.b_label
The StartPage Class
This class is not much different to the class you created previously:
class StartPage(base_frame):
def __init__(self, parent):
super().__init__(self, parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
The only difference being instead of inheriting from tk.Frame, it inherits from the base_frame class.

How to print out ttk.Combobox options in multiple frames?

In my code, there are two frames. In the first one, I put in an Add button that will produce a new frame with a Combobox. The idea is to add a few Combobox like that in the first frame, pick different options for different Combobox, and then print them out in the next frame. But when I hit the Show options button in the second frame, it doesn't print out the options that I just chose in the first frame. How can I solve this?
from tkinter import *
from tkinter import ttk
list_1 = []
class Validation_Tool(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 (PageOne, PageTwo):
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("PageOne")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def quit(self):
self.destroy()
class PageOne(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def add_compare():
global list_1
frame = Frame(self)
frame.pack()
label_1 = Label(frame, text='Options')
label_1.grid(row=0, column=0)
self.options_1 = ttk.Combobox(frame, values=['a','b','c','d','e'])
self.options_1.grid(row=1, column=0)
list_1.append(self.options_1.get())
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
next_button = Button(self, text="Next",
command=lambda: controller.show_frame("PageTwo"))
add_button = Button(self, text='Add', command=add_compare)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
next_button.place(relx=0.76, rely=0.98, anchor=SE)
add_button.place(relx=0.661, rely=0.98, anchor=SE)
class PageTwo(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def button():
label = Label(self, text=list_1)
label.pack()
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
back_button = Button(self, text="Back",
command=lambda: controller.show_frame("PageOne"))
show_button = Button(self, text='Show options', command=button)
show_button.pack()
back_button.place(relx=0.76, rely=0.98, anchor=SE)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
if __name__ == "__main__":
root = Validation_Tool()
root.geometry('400x300+430+250')
root.title("Validation Tool")
root.mainloop()
Here's a modified version of your code that will print the options selected so far when the Next is pressed. To prevent the Comboboxes from interferring with each other a list of them and an associated StringVars is kept.
Having separate StringVars avoids the problem of choosing an option on one of them from changing it on the others — i.e. a different textvar gets associated with each one.
To make collecting all the options together into list_1, a callback function named selected() has been defined and gets "bound" to Combobox selection events. This make it so that, in addition to the above, the option selected will also get appended to the global list_1, which is what the Show options button displays.
from tkinter import *
from tkinter import ttk
list_1 = []
class Validation_Tool(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.comboboxes = [] # Comboboxes created. ADDED
self.combobox_vars = [] # Vars for Comboboxes. ADDED.
self.frames = {}
for F in (PageOne, PageTwo):
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("PageOne")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def quit(self):
self.destroy()
class PageOne(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
# Combobox event handler. ADDED
def selected(event, var):
list_1.append(var.get()) # Append Combobox option selected.
def add_compare():
frame = Frame(self)
frame.pack()
label_1 = Label(frame, text='Options')
label_1.grid(row=0, column=0)
combobox_var = StringVar() # ADDED.
combobox = ttk.Combobox(frame, values=list('abcde'),
textvar=combobox_var) # For each Combobox. ADDED.
combobox.grid(row=1, column=0)
combobox.bind('<<ComboboxSelected>>', # Bind event handler. ADDED.
lambda event, var=combobox_var: selected(event, var)) # ADDED.
self.controller.comboboxes.append(combobox) # ADDED.
self.controller.combobox_vars.append(combobox_var) # ADDED.
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
next_button = Button(self, text="Next",
command=lambda: controller.show_frame("PageTwo"))
add_button = Button(self, text='Add',
command=add_compare)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
next_button.place(relx=0.76, rely=0.98, anchor=SE)
add_button.place(relx=0.661, rely=0.98, anchor=SE)
class PageTwo(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.controller = controller
def button():
label = Label(self, text=list_1)
label.pack()
quit_button = Button(self, text="Quit Program",
command=lambda: controller.quit())
back_button = Button(self, text="Back",
command=lambda: controller.show_frame("PageOne"))
show_button = Button(self, text='Show options', command=button)
show_button.pack()
back_button.place(relx=0.76, rely=0.98, anchor=SE)
quit_button.place(relx=0.98, rely=0.98, anchor=SE)
if __name__ == "__main__":
root = Validation_Tool()
root.geometry('400x300+430+250')
root.title("Validation Tool")
root.mainloop()

the tkinter widgets in my classes are not displaying

I'm trying to write a code that contains multiple pages and can be switched to when a button is clicked on. it worked initially but my widgets are not displaying, and there is neither a warning or an error message. Secondly, what is the difference between using tk and tk.TK?
from tkinter import *
import tkinter as tk
class moreTab(tk.Tk):
def __init__(self):
Tk.__init__(self)
self.geometry("1200x600")
container = Frame(self, bg='#c9e3c1')
container.pack(side = "top", fill = 'both', expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
self.frames = {}
for q in (pageone, widget):
frame = q(container,self)
self.frames[q] = frame
frame.place(x= 0,y = 0)
self.raise_frame(pageone)
def raise_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()
class widget(Frame):
def __init__(self, master, control):
Frame.__init__(self, master)
lab = tk.Label(self, text="main page")
lab.place(x = 10, y = 40)
but = tk.Button(self, text='visit start page', command=lambda:
control.raise_frame(pageone))
but.place(x = 10, y = 70)
class pageone(Frame):
def __init__(self, master, control):
Frame.__init__(self,master)
lab = Label(self, text = 'welcome to Game Analysis')
lab.place(x = 10, y = 10)
but = Button(self, text = "Start", command = lambda:
control.raise_frame(widget))
but.place(x = 10, y = 20)
app = moreTab()
app.mainloop()
It turns the issue was that you were using place(). Use the grid geometry manager. Using both import tkinter as tk and from tkinter import * is meaningless. Use one and be consistent. If you use the latter, you have everything available, hence you will write, say Button(...). But if you use the former, you will have to refer each widget like tk.Button(...).
import tkinter as tk
class moreTab(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.geometry("1200x600")
container = tk.Frame(self, bg='#c9e3c1')
container.pack(side = "top", fill = 'both', expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
self.frames = {}
for q in (pageone, widget):
frame = q(container, self)
self.frames[q] = frame
frame.grid(row=0, column=0, sticky='nsew')
self.raise_frame(pageone)
def raise_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class widget(tk.Frame):
def __init__(self, master, control):
tk.Frame.__init__(self, master)
lab = tk.Label(self, text="main page")
lab.grid(row=0, column=0, padx=10, pady=10)
but = tk.Button(self, text='visit start page', command=lambda: control.raise_frame(pageone))
but.grid(row=1, column=0, padx=10, pady=10)
class pageone(tk.Frame):
def __init__(self, master, control):
tk.Frame.__init__(self, master)
lab = tk.Label(self, text = 'welcome to Game Analysis')
lab.grid(row=0, column=0, padx=10, pady=10)
but = tk.Button(self, text = "Start", command = lambda: control.raise_frame(widget))
but.grid(row=1, column=0, padx=10, pady=10)
app = moreTab()
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

Categories

Resources