2

I have a tkinter interface with two buttons to trigger two modes of my application and a label which shows which mode it is in. When a button is clicked, the resulting function that is called takes a while to execute and come back. This results in my mouse cursor spinning and the button being essentially "frozen" until the function finishes its execution before I can click another button.

The behavior that I want is that I click a button, it runs the function asynchronously (new thread) and leaves the buttons clickable again. If another button is clicked, that first thread immediately is killed and the new function/thread starts up asynchronously.

How do I go about achieving this?

def alert_mode(var):
    print("Entering Alert Mode")
    var.set("Current mode: Alert")
    // do stuff that takes a while to return

def capture_mode(var):
    print("Entering Capture Mode")
    var.set("Current mode: Capture")
    // do stuff that takes a while to return

root = tk.Tk()
root.geometry('400x400')
var =  StringVar()
var.set("Current mode: Alert")
text = tk.Label(root, text="Current mode: Alert", textvariable=var, fg="blue", font=("Arial", 18))
text.pack(pady=8)
b = tk.Button(root, text="Alert mode", height=10, width=15, font=("Arial",14), command=lambda: alert_mode(var))
b.pack()
b2 = tk.Button(root, text="Capture mode", height=10, width=15, font=("Arial",14), command=lambda: capture_mode(var))
b2.pack()

root.mainloop()

Edit:

Okay, here is the updated code. I tried to figure out how to start and stop a thread but this doesn't quite work the way I want it to. I actually don't want both threads to be running at once. It's either alert mode or capture mode. The point is that I don't want the GUI to freeze up while either mode is running so that the user can switch to the other mode at any time.

def alert_mode(var):
    print("Entering Alert Mode")
    var.set("Current mode: Alert")
    // do stuff that takes a while to return

def capture_mode(var):
    print("Entering Capture Mode")
    var.set("Current mode: Capture")
    // do stuff that takes a while to return

def start_alert_thread(var):
    t = threading.Thread(target=alert_mode, args=(var,))
    t.start()
    t.join()

def start_capture_thread(var):
    t2 = threading.Thread(target=alert_mode, args=(var,))
    t2.start()
    t2.join()

root = tk.Tk()
var =  StringVar()
var.set("Current mode: Alert")
text = tk.Label(root, text="Current mode: Alert", textvariable=var, fg="blue", font=("Arial", 18))
text.pack(pady=8)
b = tk.Button(root, text="Alert mode", height=10, width=15, font=("Arial",14), command=lambda: start_alert_thread(var))
b.pack()
b2 = tk.Button(root, text="Capture mode", height=10, width=15, font=("Arial",14), command=lambda: start_capture_thread(var))
b2.pack()

root.mainloop()
noblerare
  • 10,277
  • 23
  • 78
  • 140

2 Answers2

1

Use threading,

import threading
option = 0

def buttonOne():
    global option
    if option == 2:
        "kill statement (not sure what)"
        option = 1
    else:
        option = 1

def buttonTwo():
    global option
    if option == 1:
        "kill statement (not sure what)"
        option = 2
    else:
        option = 2

have the button run a function like this.

def threadButtonOne():
    threading.Thread(target=buttonOne).start()
  • This is what I've found on killing threads, [link 1](http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python), [link 2](http://stackoverflow.com/questions/15729498/how-to-start-and-stop-thread) – Eli Kerrison-Male Nov 23 '16 at 05:27
1

I got way out for such condition:

Condition:

Running selenium webdriver with python and tkinter. When play button is pressed from where handle goes to python program, tkinter GUI window turns into "Not responding" mode, but python program continues. Note: indent- is just a placeholder, like indentation is important in python

Solution:

import threading, tkinter  # and so on

def python_main( ): 
    input("Enter number of users") #and so on.
    def python_sub( ): #and complete program of multiple functions
        pass

tkwindow = tk.Tk()

def mid():
    th = threading.Thread(target=python_main)
    th.start()

def tkinter_func():
    button = tk.Button(tkwindow, text= "press me", border=0, command=mid) 
    button.place(x=4,y=4)

tkwindow.mainloop()

Description: No need for wait. NO auto run program.

Abdul Aziz
  • 31
  • 5