Search code examples
python-3.xtkintervisual-studio-codetk-toolkitttk

tkinter error calling function through entries in listbox


Recently, I tried to make a full application window with a side panel menu with separate frames running some functions and submitting forms in the canvas frame.

But I found that every time I click on any entry in listbox it runs the function or method without clearing the existing one .

I tried destroy() and forget() didn't work for me (maybe I didn't know exactly how to use it?!, and the destroy() function prevent using the function again till I close the whole application and run it again!) this is a photo of my problem

this is my code :

import tkinter as tk
from tkinter import ttk


class MainWindow() :

    def __init__(self,root):


        # menu left
        self.menu_upper_frame = tk.Frame(root, bg="#dfdfdf")

        self.menu_title_label = tk.Label(self.menu_upper_frame, text="menu title", bg="#dfdfdf")
        self.menu_title_label.pack()

        self.menu_left_container = tk.Frame(root, width=150, bg="#ababab")
        self.menu_left_upper = tk.Frame(self.menu_left_container, width=150, height=150, bg="red")

        self.menu_left_upper.pack(side="top", fill="both", expand=True)

        # create a listbox of items
        self.Lb1 = tk.Listbox(self.menu_left_upper,bg ="red", borderwidth=0, highlightthickness=0 )

        self.Lb1.insert(1, "Python")
        self.Lb1.insert(2, "Perl")
        self.Lb1.insert(3, "C")
        self.Lb1.insert(4, "PHP")
        self.Lb1.insert(5, "JSP")
        self.Lb1.insert(6, "Ruby")

        self.Lb1.bind("<<ListboxSelect>>", self.OnClick )   #return selected item
        self.Lb1.pack(fill="both", expand=True, pady=50 )


        # right area
        self.inner_title_frame = tk.Frame(root, bg="#dfdfdf")

        self.inner_title_label = tk.Label(self.inner_title_frame, text="inner title", bg="#dfdfdf")
        self.inner_title_label.pack()

        self.canvas_area = tk.Canvas(root, width=500, height=400, background="#ffffff")
        self.canvas_area.grid(row=1, column=1)

        # status bar
        self.status_frame = tk.Frame(root)
        self.status = tk.Label(self.status_frame, text="this is the status bar")
        self.status.pack(fill="both", expand=True)

        self.menu_upper_frame.grid(row=0, column=0, rowspan=2, sticky="nsew")
        self.menu_left_container.grid(row=1, column=0, rowspan=2, sticky="nsew")
        self.inner_title_frame.grid(row=0, column=1, sticky="ew")
        self.canvas_area.grid(row=1, column=1, sticky="nsew") 
        self.status_frame.grid(row=2, column=0, columnspan=2, sticky="ew")

        root.grid_rowconfigure(1, weight=1)
        root.grid_columnconfigure(1, weight=1)

    def OnClick(self,event):

        widget = event.widget
        selection = widget.curselection()
        value = widget.get(selection)
        if value == 'Python':
            self.tabtop()




    def tabtop(self):

        self.tabControl = ttk.Notebook(self.canvas_area, width=400)          # Create Tab Control


        self.tab1 = ttk.Frame(self.tabControl)             # Create a tab 
        self.tab2 = ttk.Frame(self.tabControl)
        self.tab3 = ttk.Frame(self.tabControl)
        self.tab4 = ttk.Frame(self.tabControl)
        self.tab5 = ttk.Frame(self.tabControl)

        self.tabControl.add(self.tab1, text='Login data' )      # Add the tab

        self.tabControl.add(self.tab2, text='Permission')
        self.tabControl.add(self.tab3, text='Roles')
        self.tabControl.add(self.tab4, text='Personal data')
        self.tabControl.add(self.tab5, text='Business data')
        self.tabControl.pack(expand=1, fill="both")  # Pack to make visible

        self.l2 = tk.Label(self.tab2, text="label 2").pack()
        self.l3 = tk.Label(self.tab3, text="label 3").pack()


root = tk.Tk()
root.title("Control Panel")
root.style = ttk.Style()
root.style.theme_use("clam")
user = MainWindow(root)

root.mainloop()

Solution

  • If what you're really asking is how to replace an existing notebook with a new notebook, all you need to do is call destroy() on the old notebook before creating the new one.

    First, define self.tabControl to None somewhere in MainWindow.__init__. Then, in tabtop you can delete the old notebook before creating the new one:

    def tabtop(self):
        if self.tabControl is not None:
            self.tabControl.destroy()
    
        ...