在单独的线程中运行Tkinter窗体

2024-05-07 22:22:30 发布

您现在位置:Python中文网/ 问答频道 /正文

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

这是我的模块:

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

它似乎工作得很好,除非我从下面的测试程序调用它,否则它似乎不允许我的测试程序继续,即使在不同的线程中启动。

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

我认为,也许我的问题是我应该在模块本身中创建一个新线程,但我只是想尽量保持简单,因为我对Python还不熟悉。

不管怎样,提前谢谢你的帮助。

编辑:为了清楚起见,我只是想做一个模块,将在Tkinter窗口中显示一个图像,以便我可以使用这个模块,任何时候我想显示一个图像。我遇到的问题是,任何时候一个程序使用这个模块,它都无法恢复,直到Tkinter窗口关闭。


Tags: 模块图像imageimportselfinittkinterdef
3条回答

据我所知,Tkinter不喜欢玩其他的线。看这篇文章…I Need a little help with Python, Tkinter and threading

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

你的项目需要使用Tkinter吗?我喜欢特金特。它“又快又脏。”—但是在很多情况下,其他的GUI套件是可行的。

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

主要的警告是工人不能与Tkinter小部件交互。它们必须将数据写入队列,而您的主GUI线程必须轮询该队列。

如果你所做的只是显示图像,你可能根本不需要线程。只有当您有一个长时间运行的进程,否则会阻塞GUI时,线程才有用。Tkinter可以轻松处理数以百计的图像和窗口,而不费吹灰之力。

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

在大多数系统上,应该可以使用以下方法启动默认查看器:

import subprocess 

subprocess.Popen("yourimage.png")

相关问题 更多 >