在单独的线程中运行Tkinter表单

我已经写了一个简短的模块,可以传递一个图像,只需创build一个Tkinter窗口并显示它。 我遇到的问题是,即使当我实例化并调用在单独的线程中显示图像的方法时,主程序将不会继续,直到Tkinter窗口closures。

这是我的模块:

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() 

它似乎工作正常,除非我从我的testing程序,如下所示调用它,它似乎不会允许我的testing程序继续,即使在不同的线程启动。

 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..." 

我认为也许我的问题是,我应该在模块本身内创build一个新的线程,但我只是想尽量保持简单,因为我是Python的新手。

无论如何,在此先感谢您的帮助。

编辑:为了清晰起见,我只是想做一个模块,将显示在Tkinter窗口中的图像,以便我可以使用这个模块,任何时候我想显示一个图像。 我遇到的问题是程序使用这个模块的任何时候,只有在Tkinter窗口closures之后才能恢复。

从你的评论听起来就像你根本不需要GUI。 只需将图像写入磁盘并调用外部查看器即可。

在大多数系统上,应该可以使用这样的方式启动默认查看器:

 import subprocess subprocess.Popen("yourimage.png") 

Tkinter不是线程安全的,普遍的共识是Tkinter不能在非主线程中工作。 如果您重写代码以使Tkinter在主线程中运行,则可以让您的工作线程在其他线程中运行。

主要的警告是,工作人员不能与Tkinter小部件进行交互。 他们将不得不将数据写入队列,并且您的主GUI线程将不得不轮询该队列。

如果你正在做的是显示图像,你可能根本不需要线程。 线程只有当你有一个长时间运行的进程,否则将阻止的GUI是有用的。 Tkinter可以轻松处理数百个图像和窗口,而不会出汗。

据我所知,Tkinter不喜欢玩其他线程。 看到这篇文章… 我需要一点帮助Python,Tkinter和线程

解决的办法是在主线程中创build一个(可能是隐藏的)顶层,产生一个单独的线程来打开图像等,并使用共享队列将消息发送回Tk线程。

您是否需要为您的项目使用Tkinter? 我喜欢Tkinter。 这是“快而肮脏”。 – 但是还有很多情况下,其他GUI套件是要走的路。

我试图从一个单独的线程运行tkinter,不是一个好主意,它冻结。 有一个解决scheme工作。 在主线程中运行gui,并将事件发送到主gui。 这是类似的例子,它只是显示一个标签。

 import Tkinter as t global root; root = t.Tk() root.title("Control center") root.mainloop() def new_window(*args): global root print "new window" window = t.Toplevel(root) label = t.Label(window, text="my new window") label.pack(side="top", fill="both", padx=10, pady=10) window.mainloop() root.bind("<<newwin>>",new_window) #this can be run in another thread root.event_generate("<<newwin>>",when="tail")