如何创建不阻塞的Python tkinter窗口

时间:2018-10-24 10:53:08

标签: python multithreading tkinter dialog blocking

我想用Tkinter创建一个非阻塞消息窗口。当另一个功能正在等待答复时,这是为了显示等待消息。收到回复后,可以自动关闭窗口。我设法在网上找到了一些信息,并进行了以下操作:

import tkinter as tk
import threading
import time

class Show_Azure_Message(threading.Thread):
    def __init__(self, message):
        self.thread = threading.Thread.__init__(self)
        self.message = message
        self.start()

    @staticmethod
    def callback():
        return

    def destroy(self):
        self.root.quit()

    #run will be called from self.start()
    def run(self):
        self.root = tk.Tk()
        self.root.protocol("WM_DELETE_WINDOW", self.callback)
        self.t2 = tk.Text(self.root, height=10, borderwidth=0, wrap=tk.WORD)
        self.t2.insert(1.0, self.message)
        self.t2.grid(padx=5,row=2)
        self.t2.config(state=tk.DISABLED)
        self.root.mainloop()

App = Show_Azure_Message('Hello')
for i in range(0,2):
    print(i)
    time.sleep(1)

App.destroy()

当我将其作为主脚本执行时,它运行良好,但是当我收到以下错误后,想立即使用Tkinter运行另一个gui应用程序时 RuntimeError:主线程不在主循环中

同样,当我在App.destroy()之后运行另一段代码时。然后,应用程序窗口没有关闭,应用程序继续运行。

root = tk.Tk()
label = tk.Label(root, text='Hello2')
label.pack()
root.mainloop()

所以我可能做错了,但我无法找出问题所在。其次,我对Python线程没有太多经验,因此也许我在这里错过了一些琐碎的事情。

致谢, 吉尔特

1 个答案:

答案 0 :(得分:0)

我认为,如果您真的想那样做(请查看文章的评论部分),则应该改用Toplevel窗口,因为它们不需要主循环,这使事情在我眼中变得更加轻松

如果需要的话,这就是我的处理方式

from tkinter import *
import threading
import time

class Show_Azure_Message(Toplevel):
    def __init__(self,master,message):
        Toplevel.__init__(self,master) #master have to be Toplevel, Tk or subclass of Tk/Toplevel
        self.title('')
        self.attributes('WM_DELETE_WINDOW',self.callback)
        self.resizable(False,False)
        Label(self,text=message,font='-size 25').pack(fill=BOTH,expand=True)
        self.geometry('250x50+%i+%i'%((self.winfo_screenwidth()-250)//2,(self.winfo_screenheight()-50)//2))

    def callback(self): pass

BasicApp=Tk()
App = Show_Azure_Message(BasicApp,'Hello')
for i in range(0,2):
    print(i)
    time.sleep(1)

App.destroy()