Home > Net >  Navigating through pages in customtkinter python?
Navigating through pages in customtkinter python?

Time:12-19

I feel like my question is pretty straightforward, but I just cant seem to figure out how to do this. I'm currently creating a GUI project with CustomTkInter and trying to make a button that navigates through to the next page, but I'm not sure how to do this? I'm trying to link different pages together, essentially just trying to have a multi-page project, I've tried to apply the solution for the normal tkinter to my customtkinter - but its not worked so far and its throwing me some errors (specifically an error about a master not being defined)

This is what I have so far

import tkinter
import tkinter.messagebox
import customtkinter
from PIL import Image
import os

customtkinter.set_appearance_mode("Dark")  # Modes: "System" (standard), "Dark", "Light"
customtkinter.set_default_color_theme("green")  # Themes: "blue" (standard), "green", "dark-blue"

class Page(customtkinter.CTkFrame):
    def __init__(self):
        customtkinter.CTkFrame.__init__()
    def show(self):
        self.lift()
            
class Page1(Page):
    def __init__(self):
        Page.__init__()

class HomePage(customtkinter.CTkFrame):
   def __init__(self):
        super().__init__()
        
        self.title("IMS")
        self.geometry(f"{1300}x{800}")
        
        self.rowconfigure((0), weight=1)
        self.columnconfigure((0), weight=1)
        self.rowconfigure((1, 2), weight=1)     
        self.columnconfigure((1,2), weight=1)   
        self.rowconfigure((3), weight=1)
        
        image_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "images")
        self.logoImage = customtkinter.CTkImage(Image.open(os.path.join(image_path, "logo.png")), size=(150, 66))        
        
        self.titleLogo = customtkinter.CTkLabel(master=self, text="", image=self.logoImage)
        self.titleLogo.grid(row=0, column=1, padx=0, pady=0)
        
        self.categoriesButton = customtkinter.CTkButton(master=self, border_width=2, text_color=("gray10", "#DCE4EE"),font=("",33), width=150, height=50, text="Categories", command=Page1.show())
        self.categoriesButton.grid(row=2, column=0, padx=(50, 50), pady=(0, 40), sticky="nsew", columnspan=3)
        



if __name__ == "__main__":
    app = HomePage()
    app.mainloop()

Would appreciate any help, ty :)

CodePudding user response:

here's a great CTk doc that could help with your problem https://felipetesc.github.io/CtkDocs/#/multiple_frames

i made some minor changes because i was getting some error running sample 1 with python 3.9.13

import tkinter
import customtkinter

DARK_MODE = "dark"
customtkinter.set_appearance_mode(DARK_MODE)
customtkinter.set_default_color_theme("dark-blue")


class App(customtkinter.CTk):

frames = {"frame1": None, "frame2": None}

def frame1_selector(self):
    App.frames["frame2"].pack_forget()
    App.frames["frame1"].pack(in_=self.right_side_container,side=tkinter.TOP, fill=tkinter.BOTH, expand=True, padx=0, pady=0)

def frame2_selector(self):
    App.frames["frame1"].pack_forget()
    App.frames["frame2"].pack(in_=self.right_side_container,side=tkinter.TOP, fill=tkinter.BOTH, expand=True, padx=0, pady=0)

def __init__(self):
    super().__init__()
    # self.state('withdraw')
    self.title("Change Frames")

    self.geometry("{0}x{0} 0 0".format(self.winfo_screenwidth(), self.winfo_screenheight()))

    # contains everything
    main_container = customtkinter.CTkFrame(self)
    main_container.pack(fill=tkinter.BOTH, expand=True, padx=10, pady=10)

    # left side panel -> for frame selection
    left_side_panel = customtkinter.CTkFrame(main_container, width=150)
    left_side_panel.pack(side=tkinter.LEFT, fill=tkinter.Y, expand=False, padx=10, pady=10)

    # buttons to select the frames
    bt_frame1 = customtkinter.CTkButton(left_side_panel, text="Frame 1", command=self.frame1_selector)
    bt_frame1.grid(row=0, column=0, padx=20, pady=10)

    bt_frame2 = customtkinter.CTkButton(left_side_panel, text="Frame 2", command=self.frame2_selector)
    bt_frame2.grid(row=1, column=0, padx=20, pady=10)

    # right side panel -> to show the frame1 or frame 2
    self.right_side_panel = customtkinter.CTkFrame(main_container)
    self.right_side_panel.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=True, padx=10, pady=10)

    self.right_side_container = customtkinter.CTkFrame(self.right_side_panel,fg_color="#000811")
    self.right_side_container.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=True, padx=0, pady=0)

    App.frames['frame1'] = customtkinter.CTkFrame(main_container,fg_color="red")
    bt_from_frame1 = customtkinter.CTkButton(App.frames['frame1'], text="Test 1", command=lambda:print("test 1") )
    bt_from_frame1.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)

    App.frames['frame2'] = customtkinter.CTkFrame(main_container,fg_color="blue")
    bt_from_frame2 = customtkinter.CTkButton(App.frames['frame2'], text="Test 2", command=lambda:print("test 2") )
    bt_from_frame2.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)

a = App()
a.mainloop()

CodePudding user response:

i made a very basic template that you could use and modify as you want or just take the principle out of it.

import tkinter
import customtkinter

DARK_MODE = "dark"
customtkinter.set_appearance_mode(DARK_MODE)
customtkinter.set_default_color_theme("dark-blue")


class App(customtkinter.CTk):

def __init__(self):
    super().__init__()
    
    self.title("Change Frames")
    # remove title bar , page reducer and closing page !!!most have a quit button with app.destroy!!! (this app have a quit button so don't worry about that)
    self.overrideredirect(True)
    # make the app as big as the screen (no mater wich screen you use) 
    self.geometry("{0}x{1} 0 0".format(self.winfo_screenwidth(), self.winfo_screenheight()))
    

    # root!
    self.main_container = customtkinter.CTkFrame(self, corner_radius=10)
    self.main_container.pack(fill=tkinter.BOTH, expand=True, padx=10, pady=10)

    # left side panel -> for frame selection
    self.left_side_panel = customtkinter.CTkFrame(self.main_container, width=150, corner_radius=10)
    self.left_side_panel.pack(side=tkinter.LEFT, fill=tkinter.Y, expand=False, padx=5, pady=5)
    
    self.left_side_panel.grid_columnconfigure(0, weight=1)
    self.left_side_panel.grid_rowconfigure((0, 1, 2, 3), weight=0)
    self.left_side_panel.grid_rowconfigure((4, 5), weight=1)
    
    
    # self.left_side_panel WIDGET
    self.logo_label = customtkinter.CTkLabel(self.left_side_panel, text="Welcome! \n", font=customtkinter.CTkFont(size=20, weight="bold"))
    self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10))
    
    self.scaling_label = customtkinter.CTkLabel(self.left_side_panel, text="UI Scaling:", anchor="w")
    self.scaling_label.grid(row=7, column=0, padx=20, pady=(10, 0))
    
    self.scaling_optionemenu = customtkinter.CTkOptionMenu(self.left_side_panel, values=["80%", "90%", "100%", "110%", "120%"],
                                                           command=self.change_scaling_event)
    self.scaling_optionemenu.grid(row=8, column=0, padx=20, pady=(10, 20), sticky = "s")
    
    self.bt_Quit = customtkinter.CTkButton(self.left_side_panel, text="Quit", fg_color= '#EA0000', hover_color = '#B20000', command= self.close_window)
    self.bt_Quit.grid(row=9, column=0, padx=20, pady=10)
    
    # button to select correct frame IN self.left_side_panel WIDGET
    self.bt_dashboard = customtkinter.CTkButton(self.left_side_panel, text="Dashboard", command=self.dash)
    self.bt_dashboard.grid(row=1, column=0, padx=20, pady=10)

    self.bt_statement = customtkinter.CTkButton(self.left_side_panel, text="Statement", command=self.statement)
    self.bt_statement.grid(row=2, column=0, padx=20, pady=10)
    
    self.bt_categories = customtkinter.CTkButton(self.left_side_panel, text="Manage Categories", command=self.categories)
    self.bt_categories.grid(row=3, column=0, padx=20, pady=10)
    

    # right side panel -> have self.right_dashboard inside it
    self.right_side_panel = customtkinter.CTkFrame(self.main_container, corner_radius=10, fg_color="#000811")
    self.right_side_panel.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=True, padx=5, pady=5)
    
    
    self.right_dashboard = customtkinter.CTkFrame(self.main_container, corner_radius=10, fg_color="#000811")
    self.right_dashboard.pack(in_=self.right_side_panel, side=tkinter.TOP, fill=tkinter.BOTH, expand=True, padx=0, pady=0)
    

#  self.right_dashboard   ----> dashboard widget  
def dash(self):
    
    self.clear_frame()
    self.bt_from_frame1 = customtkinter.CTkButton(self.right_dashboard, text="dash", command=lambda:print("test dash") )
    self.bt_from_frame1.grid(row=0, column=0, padx=20, pady=(10, 0))
    self.bt_from_frame2 = customtkinter.CTkButton(self.right_dashboard, text="dash 1", command=lambda:print("test dash 1" ) )
    self.bt_from_frame2.grid(row=1, column=0, padx=20, pady=(10, 0))

#  self.right_dashboard   ----> statement widget
def statement(self):
    self.clear_frame()
    self.bt_from_frame3 = customtkinter.CTkButton(self.right_dashboard, text="statement", command=lambda:print("test statement") )
    self.bt_from_frame3.grid(row=0, column=0, padx=20, pady=(10, 0))
    
#  self.right_dashboard   ----> categories widget
def categories(self):
    self.clear_frame()
    self.bt_from_frame4 = customtkinter.CTkButton(self.right_dashboard, text="categories", command=lambda:print("test cats") )
    self.bt_from_frame4.grid(row=0, column=0, padx=20, pady=(10, 0))


# Change scaling of all widget 80% to 120%
def change_scaling_event(self, new_scaling: str):
    new_scaling_float = int(new_scaling.replace("%", "")) / 100
    customtkinter.set_widget_scaling(new_scaling_float)
    
    
 # close the entire window    
def close_window(self): 
        App.destroy(self)
        
        
# CLEAR ALL THE WIDGET FROM self.right_dashboard(frame) BEFORE loading the widget of the concerned page       
def clear_frame(self):
    for widget in self.right_dashboard.winfo_children():
        widget.destroy()


a = App()
a.mainloop()
  • Related