1

I want to write a program using Tkinter GUI, which performs a certain task in a thread. When an error occurs during the execution of the task, the program should pop up an error-window, for example using tkMessageBox. Of course the program crashes when it should pop up the messagebox from the new thread, since Tkinter isn't thread safe, but I hope that there is a solution to this problem.

Here is an easy example of a not working code (edited):

from tkinter import *
import tkMessageBox
from threading import *
import time


class App:

    def __init__(self, master):

        frame = Frame(master)
        frame.pack()

        self.button = Button(frame, text = "Task", command = self.thread_task)
        self.button.pack(side=LEFT)

    def thread_task(self):

        thread = Thread(target = self.task)
        thread.start()

    def task(self):

        #perform task...          
        time.sleep(1) #Just as a filler in the code
        #command to open an error popup, e.g. tkMessageBox.showerror("Error", "Problem occured")

root = Tk()
app = App(root)
root.mainloop()
TobPython
  • 11
  • 2

1 Answers1

0

You can use try-except inside a thread.

Here is an example based on your code (edited to work with Python 2):

from Tkinter import *
import tkMessageBox
from threading import *


class App:
    def __init__(self, master):
        frame = Frame(master)
        frame.pack()

        self.button = Button(frame, text="Task", command=self.thread_task)
        self.button.pack(side=LEFT)

    def thread_task(self):
        thread = Thread(target=self.task)
        thread.start()


    def task(self):
        try:
            time.sleep(1)
            self.button["text"] = "Started"
            self.button["state"] = "disabled"
            raise ValueError  # or anything else
        except:
            tkMessageBox.showerror("Error", "Problem occured")
        self.button["text"] = "Task"
        self.button["state"] = "normal"

if __name__ == "__main__":
    root = Tk()
    app = App(root)
    root.mainloop()
Demian Wolf
  • 1,698
  • 2
  • 14
  • 34
  • 1
    Hi, thanks for the answer. In your code, the messagebox still opens in the thread, which leads to a crash of the program. I edited my code and tried to explain my problem more clearly. I hope this is a better help (I am using Python 2.7) – TobPython May 06 '20 at 14:02
  • @TobPython I have tried to insert the `time.sleep(1)` inside the `try` block -- everything works fine, without freezing. Maybe you're trying to change some properties of Tkinter widgets from the `task` function. If so, it's a bad idea to use threading here (because you will mess up the Tkinter mainloop), and you should consider using `root.after(ms, func)` instead. Please, tell a bit more about what's going on in the `task` function. What are you trying to call there? – Demian Wolf May 06 '20 at 14:20