Search code examples
pythontkinterttk

How to solve Tkinter Button Binding Causing errors on Mac?


I'm running a python (3.10.2) Tkinter GUI application on Mac OS X (12.1). The code is simply just binding the event to a Combobox to create a new page. This all works fine, but sometimes when you click on the back button, it gives me the error code "Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)". I've tried multiple different combinations with no success. I've tried using entry boxes from Tkinter rather than comboboxes from ttk. This still led to the same error. I then tired using a submit button instead of a combobox widget. I never experienced the error once, but in another one of my projects I wanted to bind the enter key and have a submit button which still gave me the same error. This allowed me to determine it had something to do with event binding. Next, I changed my python version (I changed from Python 3.10.0 to Python 3.9, then I upgraded to Python 3.10.2, both of these had no impact whatsoever). After this, I played around and realized that the button command itself wasn't even executing. The button was being clicked, and this killed the code for some reason. I'm really confused about the entire situation. What makes even less sense is that sometimes it occurs and sometimes it doesn't. Some runs allow it to be successful, while others don't. The other thing that I saw with my other project was that if you ran a different command that deleted the page and created a new one, the key bind would work. All of this confused me even more than I already was.


# Importing tkinter and ttk
from tkinter import *
from tkinter import ttk

# Creating the original page
def HomePage():

    # Creating new tkinter window with the size of the screen as the height and width
    # I made its name HomePage.root in order to make it accessible to other functions without the hassle of global and local
    # I also made height and width like this in order to access them in the next function
    HomePage.root = Tk()
    height = HomePage.root.winfo_screenheight()
    width = HomePage.root.winfo_screenwidth()
    HomePage.root.geometry("%dx%d" % (width, height))

    # Creating combobox and binding it to NewPage function
    combo = ttk.Combobox(HomePage.root)
    combo.pack()
    combo.bind("<Return>",NewPage)

    # Running Mainloop
    HomePage.root.mainloop()

# NewPage function to go into new page

# Back command
def Back(control, func):
    print("yay I entered the command")
    control.destroy()
    func()

def NewPage(e):

    # Destroying old page and creating new page
    HomePage.root.destroy()
    NewPage.window = Tk()
    height = NewPage.window.winfo_screenheight()
    width = NewPage.window.winfo_screenwidth()
    NewPage.window.geometry("%dx%d" % (width, height))

    # Creating button
    back = Button(NewPage.window, text="back", command=lambda: Back(NewPage.window, HomePage))
    back.pack(side=BOTTOM)

    # Running Mainloop
    NewPage.window.mainloop()

# Running HomePage function
HomePage()


Solution

  • I worked with my code changing and modifying it until I had an idea. Rather than setting the button command, why not bind the button with a mouse click? I tried this, and it worked!

    Here is my code:

    # Importing tkinter and ttk
    from tkinter import *
    from tkinter import ttk
    
    # Creating the original page
    def HomePage():
    
        # Creating new tkinter window with the size of the screen as the height and width
        # I made its name HomePage.root in order to make it accessible to other functions without the hassle of global and local
        # I also made height and width like this in order to access them in the next function
        HomePage.root = Tk()
        height = HomePage.root.winfo_screenheight()
        width = HomePage.root.winfo_screenwidth()
        HomePage.root.geometry("%dx%d" % (width, height))
    
        # Creating combobox and binding it to NewPage function
        combo = ttk.Combobox(HomePage.root)
        combo.pack()
        combo.bind("<Return>",NewPage)
    
        # Running Mainloop
        HomePage.root.mainloop()
    
    # Back command
    def Back(e,control, func):
        print("yay I entered the command")
        control.destroy()
        func()
    
    # NewPage function to go into new page
    def NewPage(e):
    
        # Destroying old page and creating new page
        HomePage.root.destroy()
        NewPage.window = Tk()
        height = NewPage.window.winfo_screenheight()
        width = NewPage.window.winfo_screenwidth()
        NewPage.window.geometry("%dx%d" % (width, height))
    
        # Creating button
        back = Button(NewPage.window, text="back")
        back.pack(side=BOTTOM)
        back.bind("<Button 1>", lambda event, control=NewPage.window, func=HomePage: Back(event, control, func))
    
        # Running Mainloop
        NewPage.window.mainloop()
    
    # Running HomePage function
    HomePage()