如何使用自定义 TKinter 使框架内的按钮影响其自身框架外的某些内容?

问题描述 投票:0回答:1

如何使框架内的按钮影响其框架外的内容?我是编程新手,无法自己解决这个问题。这是我的代码和一些图片,准确地显示了我想要做的事情。任何帮助将不胜感激。

import tkinter
import tkinter.messagebox
import customtkinter


class SidebarFrame(customtkinter.CTkFrame):
    def __init__(self, master):
        super().__init__(master, corner_radius=0)
        self.grid_rowconfigure(4, weight=1)

        self.logo_label = customtkinter.CTkLabel(self, text="Board Game\nBorrow", font=customtkinter.CTkFont(size=20, weight="bold"))       #Title
        self.logo_label.grid(row=0, column=0, padx=30, pady=(20, 10))

        self.functionsframe = FunctionsSidebarFrame(self)                                                                                 #Call Functions Frame
        self.functionsframe.grid(row=1, column=0, padx=10, pady=10)
        self.functions_remove()                                                                                                           #Hide Functions Frame

        self.loginframe = LoginSidebarFrame(self)                                                                                         #Call Login Frame
        self.loginframe.grid(row=1, column=0, padx=10, pady=10)

        self.sidebar_button_1 = customtkinter.CTkButton(self, text="Login", command=self.login)
        self.sidebar_button_1.grid(row=2, column=0, padx=10, pady=10)

    def login_remove(self):
        self.loginframe.grid_remove()

    def login_show(self):
        self.loginframe.grid()

    def functions_remove(self):
        self.functionsframe.grid_remove()

    def functions_show(self):
        self.functionsframe.grid()

    def login(self):
        if self.loginframe.winfo_ismapped():
            self.login_remove()
            self.functions_show()
        elif not self.loginframe.winfo_ismapped():
            self.login_show()
            self.functions_remove()

class FunctionsSidebarFrame(customtkinter.CTkFrame):
    def __init__(self, master):
        super().__init__(master, width=120, corner_radius=8)
        self.grid_rowconfigure(4, weight=1)

        self.sidebar_button_1 = customtkinter.CTkButton(self, text="Veiw Game List", command=self.viewGames)                                #Side Button 1 (View Game List)
        self.sidebar_button_1.grid(row=1, column=0, padx=10, pady=10)

        self.sidebar_button_2 = customtkinter.CTkButton(self, text="Request Game", command=self.requestGame)                                #Side Button 2 (Request Game)
        self.sidebar_button_2.grid(row=2, column=0, padx=10, pady=10)

        self.sidebar_button_3 = customtkinter.CTkButton(self, text="Add Game", command=self.addGame)                                        #Side Button 3 (Add Game)
        self.sidebar_button_3.grid(row=3, column=0, padx=10, pady=10)

    def viewGames(self):
        print("View Games")

    def requestGame(self):
        print("Request Game")

    def addGame(self):
        print("Add Game")

class LoginSidebarFrame(customtkinter.CTkFrame):
    def __init__(self, master):
        super().__init__(master, width=120, corner_radius=8)

        text = customtkinter.CTkLabel(self, text="Please Login", font=customtkinter.CTkFont(size=15, weight="bold"))                        #Title
        text.grid(row=0, column=0, padx=10, pady=10)


class ScrollFrame(customtkinter.CTkScrollableFrame):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)


        self._parent_frame.grid(row=0, column=0, rowspan=3, padx=(20,0), pady=(40,70), sticky="nsew")

        self.label = customtkinter.CTkLabel(self, text="Game List", font=customtkinter.CTkFont(size=18, weight="bold"))
        self.label.grid(row=0, column=0, padx=20)
        # Add Game List here

class GeneralFrame(customtkinter.CTkFrame):
    def __init__(self, master):
        super().__init__(master)
        
        label = customtkinter.CTkLabel(self, text="Login Frame")
        label.grid(row=0, column=0, padx=20, pady=20)

class App(customtkinter.CTk):
    def __init__(self):
        super().__init__()

        self.title("Board Game Borrow")
        self.geometry(f"{1100}x{580}")

        self.grid_columnconfigure(1, weight=1)
        self.grid_columnconfigure(2, weight=0)
        self.grid_rowconfigure((0, 1, 2), weight=1)

        self.sidebar_frame = SidebarFrame(self)                                                                                             #Call Sidebar Frame
        self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew")

        self.top_button1 = customtkinter.CTkButton(self, text="Create Account", width=15, height=10, command=self.create_account)                                                              #Top Button
        self.top_button1.grid(row=0, column=3, padx=(20, 80), pady=10, sticky="ne")

        self.top_button2 = customtkinter.CTkButton(self, text="Sign In", width=15, height=10, command=self.login)                                                 #Top Button
        self.top_button2.grid(row=0, column=3, padx=20, pady=10, sticky="ne")

        self.checkbox = customtkinter.CTkCheckBox(self, text="Sidebar", command=self.sidebar)                                               #Call Checkbox
        self.checkbox.grid(row=2, column=1, padx=20, pady=20, sticky="ws")
        self.checkbox.select()

        self.textbox = customtkinter.CTkTextbox(self, width=100)                                                                            #Call Textbox
        self.textbox.grid(row=0, column=2, padx=20, pady=(40,70), sticky="nsew", rowspan=3, columnspan=2)
        self.textbox.insert("end", "Welcome to Board Game Borrow\n\n")

        self.exit = customtkinter.CTkButton(self, text="Exit", command=self.quit)                                                           #Exit Button
        self.exit.grid(row=2, column=3, padx=20, pady=20, sticky="es")

        self.current_frame = None

        button1 = customtkinter.CTkButton(self, text="Switch to Scroll Frame", command=lambda: self.switch_frame(ScrollFrame))
        button1.grid(row=2, column=1, padx=20, pady=20, sticky="es")

        button2 = customtkinter.CTkButton(self, text="Switch to Login Frame", command=lambda: self.switch_frame(GeneralFrame))
        button2.grid(row=2, column=1, padx=180, pady=20, sticky="es")

        button3 = customtkinter.CTkButton(self, text="Remove Frame", command=lambda: self.remove_frame())
        button3.grid(row=2, column=2, padx=20, pady=20, sticky="es")

    def switch_frame(self, frame_class):
        new_frame = frame_class(self)
        if self.current_frame is not None:
            self.current_frame.grid_remove()
        self.current_frame = new_frame
        self.current_frame.grid(row=0, column=1)
        print(self.current_frame)

    def remove_frame(self):
        self.current_frame.grid_remove()
        self.current_frame = None
        print(self.current_frame)

    def sidebar_button_event(self):
        print("sidebar_button click")

    def sidebar(self):
        if self.sidebar_frame.winfo_ismapped():
            self.hide_sidebar()
        elif not self.sidebar_frame.winfo_ismapped():
            self.show_sidebar()
    
    def hide_sidebar(self):
        self.sidebar_frame.grid_remove()

    def show_sidebar(self):
        self.sidebar_frame.grid()

    def create_account(self):
        username = customtkinter.CTkInputDialog(text="Enter usernsme", title="Login")
        text1 = username.get_input()  # waits for input
        password = customtkinter.CTkInputDialog(text="Enter password", title="Login")
        text2 = password.get_input() # waits for input
        # Add code to add username(text1) and password(text2) to a new user in the database

    def login(self):
        username = customtkinter.CTkInputDialog(text="Enter usernsme", title="Login")
        text = username.get_input()  # waits for input
        password = customtkinter.CTkInputDialog(text="Enter password", title="Login")
        text2 = password.get_input() # waits for input
        if text == "admin" and text2 == "admin":
            self.top_button2.grid_remove()
            self.top_button2 = customtkinter.CTkButton(self, text="Sign Out", width=15, height=10)
            self.top_button2.grid(row=0, column=3, padx=20, pady=10, sticky="ne")
            self.sidebar_frame.login()

    def __str__(self):
        return "App"

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

“查看游戏列表”按钮应具有与“切换到滚动框架”按钮相同的功能

这些是按钮

这就是切换到滚动框架按钮的作用

我尝试让按钮运行

App.switch_frame(ScrollFrame)
但什么也没发生。没有错误消息或任何类型的更改。

python tkinter customtkinter
1个回答
0
投票

您尝试的 App.switch_frame(ScrollFrame) 不起作用,因为它是从类而不是实例调用函数,而实例不是您看到的窗口。所以你需要从实例“app”调用该函数。

这是 OOP 的普遍问题。您经常需要类以某种方式进行交互,这只有在每个类都引用另一个类或者实例是全局的情况下才有可能。这两种解决方案都违背了使用 OOP 的目的/优点。

对于您的情况,您可以为 FunctionsSidebarFrame 类提供对应用程序实例的引用,然后您可以使用该引用来调用其 swith_frame 函数。

class FunctionsSidebarFrame(customtkinter.CTkFrame):
    def __init__(self, master, app):
        self.app = app
        ...
    def viewGames(self):
        self.app.switch_frame(ScrollFrame)

这还要求您为 SidebarFrame 类提供要传递给 FunctionsSidebarFrame 的引用。

© www.soinside.com 2019 - 2024. All rights reserved.