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

der*_*icw 5 python multithreading tkinter

我编写了一个可以传递图像的简短模块,只需创建一个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()
Run Code Online (Sandbox Code Playgroud)

它似乎工作正常,除非我从我的测试程序中调用它,如下所示,它似乎不允许我的测试程序继续,即使在另一个线程中启动.

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..."
Run Code Online (Sandbox Code Playgroud)

我想也许我的问题是我应该在模块本身内创建一个新线程,但我只想尝试保持简单,因为我是Python的新手.

无论如何,提前感谢任何帮助.

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

Bry*_*ley 13

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

主要的警告是工人无法与Tkinter小部件交互.他们必须将数据写入队列,并且您的主GUI线程必须轮询该队列.

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


Gon*_*nzo 6

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

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

import subprocess 

subprocess.Popen("yourimage.png")
Run Code Online (Sandbox Code Playgroud)