tkinter mainloop() 一旦完成就不会结束脚本

问题描述 投票:0回答:4

出于某种原因,mainloop() 没有结束。最后的 print 语句永远不会被触发,但其他一切都会触发。知道是什么原因造成的或如何解决它。即使没有线程也会发生。

import time
from tkinter.filedialog import askdirectory
from tkinter import *

def threading():
    t1=Thread(target=checkProgress)
    t1.start()

def checkProgress():
    loading_window.geometry = ("500x500")
    text = "The device is being reset. This will take a minute."
    Label(loading_window, text=text, font=('times', 12)).pack()
    loading_window.update()
    time.sleep(3)
    print("The connection is complete!")

Tk().withdraw()
download_location = askdirectory(title='Find and select the download folder', mustexist=TRUE)

loading_window = Tk()
loading_window.after(200, threading())
loading_window.mainloop()

print("Finished")
python tkinter python-multithreading mainloop
4个回答
0
投票

解决方案是在多线程时必须使用按钮。我想我尝试了一百万种不同的方法,出于某种原因,destroy() 只有在没有线程或使用按钮调用它时才能正常工作。我不知道为什么,但这很烦人。这是解决方案。主要部分是带有 destroy 命令的按钮。非常令人沮丧,我不能在函数完成休眠后简单地调用命令。我必须通过按钮调用它。

def threading():
    t1=Thread(target=work)
    t1.start()

def work():

    print("sleep time start")
    time.sleep(5)
    print("sleep time stop")
    
    Label(loading_window, text="The device is ready! Please click next.", font=('times', 12)).pack()
    Button(loading_window,text="Next",command = destroy).pack()

def destroy():
    loading_window.destroy()

loading_window = Tk()
loading_window.geometry = ("500x500")
Label(loading_window, text="The device is being reset. This will take a minute.", font=('times', 12)).pack()
threading()
loading_window.mainloop()

0
投票

因为有两个

Tk()
的实例:

  • Tk().withdraw()
    (隐藏实例)
  • loading_window = Tk()

即使你关闭了第二个实例,

mainloop()
仍然会运行,因为有一个隐藏的
Tk()
实例。

你应该只使用一个

Tk()
的实例:

import time
from threading import Thread
from tkinter.filedialog import askdirectory
from tkinter import *

def threading():
    t1=Thread(target=checkProgress)
    t1.start()

def checkProgress():
    loading_window.geometry("500x500")
    text = "The device is being reset. This will take a minute."
    Label(loading_window, text=text, font=('times', 12)).pack()
    loading_window.update()
    loading_window.deiconify()  # show the window
    time.sleep(3)
    print("The connection is complete!")
    loading_window.destroy()  # destroy the window

# only create one instance of Tk()
loading_window = Tk()
loading_window.withdraw() # hide the window
download_location = askdirectory(title='Find and select the download folder', mustexist=TRUE)
loading_window.after(200, threading)
loading_window.mainloop()

print("Finished")

注意,大多数人说不建议直接在子线程中更新 tkinter widgets,因为 tkinter 不是线程安全的。

下面是修改后的代码,以尽量减少线程中的直接更新 tkinter 小部件:

import time
from threading import Thread
from tkinter.filedialog import askdirectory
from tkinter import *

def threading():
    loading_window.deiconify()  # show the window
    t1=Thread(target=checkProgress)
    t1.start()

def checkProgress():
    time.sleep(3)
    print("The connection is complete!")
    loading_window.after(10, loading_window.destroy)  # destroy the window


loading_window = Tk()
loading_window.geometry("500x500")
text = "The device is being reset. This will take a minute."
Label(loading_window, text=text, font=('times', 12)).pack()

loading_window.withdraw() # hide the window
download_location = askdirectory(title='Find and select the download folder', mustexist=TRUE)

loading_window.after(200, threading)
loading_window.mainloop()

print("Finished")

-1
投票

你需要一些东西来破坏窗口以退出主循环。 您可以添加一个按钮来关闭窗口,或者如下所示添加一行以在完成后销毁窗口:

import tkinter as tk
from tkinter import filedialog
import time   
from threading import Thread        

def threading():
    t1=Thread(target=checkProgress)
    t1.start()

def checkProgress():
    loading_window.geometry = ("500x500")
    text = "The device is being reset. This will take a minute."
    tk.Label(loading_window, text=text, font=('times', 12)).pack()
    loading_window.update()
    time.sleep(3)
    # destroy the window
    loading_window.destroy()
    print("The connection is complete!")

if __name__=="__main__" :
    # tk().withdraw()
    download_location = filedialog.askdirectory(title='Find and select the download folder', mustexist=tk.TRUE)
    
    loading_window = tk.Tk()
    loading_window.after(200, threading)
    loading_window.mainloop()
    
    print("Finished") 

-1
投票

更新:我建议使用

Event
并在windows cmd脚本中添加
daemon=True

import time
import tkinter as tk
from threading import Thread, Event

def threading(event):
    try:
        t1=Thread(target=checkProgress, daemon=True)
        t1.start()
    except:
        print("Take the error management here ..")
    finally:
        print("Thread is running")

def checkProgress():
    root.geometry = ("500x500")
    text = "The device is being reset. This will take a minute."
    tk.Label(root, text=text, font=('times', 12)).pack()
    root.update()
    time.sleep(3)
    print("The connection is complete!")
    print("Finished")
    root.destroy()

if __name__=="__main__" :
    root = tk.Tk()
    event = Event()
    root.after(200, threading(event))   
    event.set()  
    root.mainloop()
© www.soinside.com 2019 - 2024. All rights reserved.