Search code examples
pythontkintertabviewcustomtkinter

CustomTkinter TabView button enablement between classes


I have widgets on several tabs and an overall OK button. The OK button is disabled until changes are made to the widgets and a command is called. How do I reference the OK button so that it is a recognised attribute within Entry_Done?

I have tried all sorts of variations of tab_view / app / master but have left the problem area as xxx to avoid clutter.

import customtkinter as ctk

class MyTabView(ctk.CTkTabview):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)

        self.add('tab 1')

        self.Entry = ctk.CTkOptionMenu(master=self.tab('tab 1'), values=['', 'Yes', 'No'], command=self.Entry_Done)
        self.Entry.grid(row=0, column=0, padx=20, pady=10)

    def Entry_Done(self, *_args):
        self.xxx.OKButton.configure(state='normal')

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

        self.tab_view = MyTabView(master=self)
        self.tab_view.grid(row=0, column=0, padx=20, pady=20)

        self.OKButton = ctk.CTkButton(self, text='OK', state='disabled')
        self.OKButton.grid(row=3, column=1, columnspan=1, padx=20, pady=20, sticky='ew')

app = App()
app.mainloop()

I have a feeling I need to define self.parent akin to Python 3 tkinter button command inside different class but I haven't been able to get this to work either.

UPDATE: I can get something to work if I move the Entry_Done function down to class App and call it as a command on self.Entry as command=master.Entry_Done but I still have a problem as I want to do more stuff before enabling the OK button. So, how can I call Entry_Done with this revised code please?


class MyTabView(ctk.CTkTabview):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)

        self.add('tab 1')

        self.Entry = ctk.CTkOptionMenu(master=self.tab('tab 1'), values=['', 'Yes', 'No'], command=self.Do_Stuff)
        self.Entry.grid(row=0, column=0, padx=20, pady=10)

    def Do_Stuff(master,  *_args):
        master.Entry_Done() # what to put here?

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

        self.tab_view = MyTabView(master=self)
        self.tab_view.grid(row=0, column=0, padx=20, pady=20)

        self.OKButton = ctk.CTkButton(self, text='OK', state='disabled')
        self.OKButton.grid(row=3, column=1, columnspan=1, padx=20, pady=20, sticky='ew')

    def Entry_Done(self, *_args):
        self.OKButton.configure(state='normal')
app = App()
app.mainloop()

Solution

  • For the record, this works:

    import customtkinter as ctk
    
    class MyTabView(ctk.CTkTabview):
        def __init__(self, master, **kwargs):
            super().__init__(master, **kwargs)
    
            self.add('tab 1')
    
            self.Entry = ctk.CTkOptionMenu(master=self.tab('tab 1'), values=['', 'Yes', 'No'], command=self.Do_Stuff)
            self.Entry.grid(row=0, column=0, padx=20, pady=10)
    
        def Do_Stuff(self,  *_args):
            App.Entry_Done(self)
    
    class App(ctk.CTk):
        def __init__(self):
            super().__init__()
    
            self.tab_view = MyTabView(master=self)
            self.tab_view.grid(row=0, column=0, padx=20, pady=20)
    
            self.OKButton = ctk.CTkButton(master=self, text='OK', state='disabled')
            self.OKButton.grid(row=3, column=1, columnspan=1, padx=20, pady=20, sticky='ew')
    
        def Entry_Done(self, *_args):
            self.master.OKButton.configure(state='normal')
    app = App()
    app.mainloop()
    

    As well as moving the Entry_Done function to the App class, I have added self.master to the OKButton enablement.