Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running a Tkinter form in a separate thread

I have written a short module that can be passed an image and simply creates a Tkinter window and displays it. The problem that I am having is that even when I instantiate and call the method that displays the image in a separate thread, the main program will not continue until the Tkinter window is closed.

Here is my module:

import Image, ImageTk
import Tkinter


class Viewer(Tkinter.Tk):
    def __init__(self,parent):
        Tkinter.Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

    def initialize(self):
        self.grid()

    def show(self,img):
        self.to_display = ImageTk.PhotoImage(img)
        self.label_image = Tkinter.Label(self,image=self.to_display)
        self.label_image.grid(column = 0, row = 0, sticky = "NSEW")
        self.mainloop()

It seems to work fine, except when I call it from my test program like the one below, it will not seem to allow my test program to continue, even when started in a different thread.

import Image
from viewer import Viewer
import threading

def showimage(im):
    view = Viewer(None)
    view.show(im)

if __name__ == "__main__":
    im = Image.open("gaben.jpg")
    t = threading.Thread(showimage(im))
    t.start()
    print "Program keeps going..."

I think that perhaps my problem is that I should be creating a new thread within the module itself, but I was wanting to just try and keep it simple, as I am new to Python.

Anyway, thanks in advance for any assistance.

edit: To clarity, I am just trying to make a module that will display an image in a Tkinter window, so that I can use this module any time I want to display an image. The problem that I am having is that any time a program uses this module, it cannot resume until the Tkinter window is closed.

like image 864
derricw Avatar asked May 11 '12 18:05

derricw


People also ask

Can you run Tkinter in a thread?

With Tkinter, we can call multiple functions at a time using Threading. It provides asynchronous execution of some functions in an application. In order to use a thread in Python, we can import a module called threading and subclass its Thread class.

Is Tkinter multi threaded?

To create and control multiple threads in Tkinter applications, you can use the Python threading module. The threading module is included in Python's standard library so you don't need to install it.

Is Tkinter single threaded?

Tkinter, like most other GUIs, is best used with all graphic commands in a single thread.

Is Tkinter thread safe?

Although tkinter is technically thread-safe (assuming Tk is built with --enable-threads), practically speaking there are still problems when used in multithreaded Python applications.


2 Answers

Tkinter isn't thread safe, and the general consensus is that Tkinter doesn't work in a non-main thread. If you rewrite your code so that Tkinter runs in the main thread, you can have your workers run in other threads.

The main caveat is that the workers cannot interact with the Tkinter widgets. They will have to write data to a queue, and your main GUI thread will have to poll that queue.

If all you're doing is showing images, you probably don't need threading at all. Threading is only useful when you have a long running process that would otherwise block the GUI. Tkinter can easily handle hundreds of images and windows without breaking a sweat.

like image 95
Bryan Oakley Avatar answered Oct 01 '22 08:10

Bryan Oakley


From your comments it sound's like you do not need a GUI at all. Just write the image to disk and call an external viewer.

On most systems it should be possible to launch the default viewer using something like this:

import subprocess 

subprocess.Popen("yourimage.png")
like image 20
Gonzo Avatar answered Oct 01 '22 08:10

Gonzo