首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Tkinter线程化时tkinter关闭协议

Tkinter线程化时tkinter关闭协议
EN

Stack Overflow用户
提问于 2022-10-11 14:08:53
回答 2查看 33关注 0票数 0

我有一个执行函数的小代码,同时显示一个不确定的tkinter进度条。当您让程序执行时,一切正常工作,而如果您试图通过关闭tkinter窗口来停止进程,则会得到RuntimeError:主线程不在主循环中。我知道解决方案可能是在主线程中引入bar主循环,或者使用队列,但我不清楚如何做到这一点。在这里,您可以找到一个简单的模拟函数(addit)来执行代码。提前谢谢大家!

代码语言:javascript
复制
import threading
importing tkinter module
import tkinter
import tkinter.ttk as ttk
from tkinter import messagebox
from tkinter import Button
from tkinter import Label
import sys
import time



class tkwindow(threading.Thread):


    def __init__(self):
        threading.Thread.__init__(self, daemon=True)

        
        
    def run(self):
        self.wbar=tkinter.Tk()
        self.wbar.attributes("-topmost", True) 
        self.wbar.title('Tool')
        lb=Label(self.wbar,text='Check in progress')
        lb.pack()
        pbar = ttk.Progressbar(self.wbar,orient='horizontal', length=500, mode='indeterminate')
        pbar.pack(pady=25)
        pbar.start(50) 
        self.wbar.protocol("WM_DELETE_WINDOW", self.on_closing)
        self.loopmain()
        
    def loopmain(self):
        
        self.wbar.mainloop()
        
               
        
    def quitall(self):
        
        self.wbar.quit()
        sys.exit()
      
    def on_closing(self):
        if messagebox.askokcancel("Quit", "Do you want to quit?"):
          self.wbar.quit()
          sys.exit()   
        
       

def main(): 

    mygui=tkwindow()     
    mygui.start()
    addit(2,3)
    
    mygui.quitall()
         


def addit(a,b):
    time.sleep(3)
    print(a+b)
    return


if __name__=='__main__':  
    main()
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-10-11 15:29:03

也许我已经找到了一种使用队列来做我想做的事情的方法。不幸的是,代码突然用interrupt_main扼杀了主线程,而不是像sys.exit()那样以一种很好的方式杀死主线程,但这是我目前找到的唯一解决方案。更新后的代码如下:

代码语言:javascript
复制
import threading
import tkinter
import tkinter.ttk as ttk
from tkinter import messagebox
from tkinter import Button
from tkinter import Label
import sys
import time
from queue import Queue
import _thread
import os



class tkwindow(threading.Thread):


    def __init__(self,dataq):
        threading.Thread.__init__(self, daemon=True)
        self.dataq=dataq

        
        
    def run(self):
        self.wbar=tkinter.Tk()
        self.wbar.attributes("-topmost", True) 
        self.wbar.title('Tool')
        lb=Label(self.wbar,text='Check in progress')
        lb.pack()
        pbar = ttk.Progressbar(self.wbar,orient='horizontal', length=500, mode='indeterminate')
        pbar.pack(pady=25)
        pbar.start(50) 
        self.dataq.put(0)
        self.loopmain()
        
    def loopmain(self):
        self.wbar.protocol("WM_DELETE_WINDOW", self.on_closing)
        self.wbar.after(100,self.checkq)
        self.wbar.mainloop()
        
        
    def checkq(self):
        
        v=self.dataq.get()
        if v:
          if messagebox.askokcancel("Quit", "Do you want to quit?"):
            self.wbar.quit()
            os._exit(0)  #or alternatively _thread.interrupt_main()
            
         
        
    def quitall(self):
        
        self.wbar.quit()
        sys.exit()

      
    def on_closing(self):
        self.dataq.put(1)
        self.checkq()




def main(): 
    dataq=Queue()
    mygui=tkwindow(dataq)     
    mygui.start()
    addit(2,3)   
    mygui.quitall()
    


def addit(a,b):

    time.sleep(3)
    print(a+b)
    return

    
   

if __name__=='__main__':  
    main()
票数 0
EN

Stack Overflow用户

发布于 2022-10-11 14:36:48

代码的结构是错误的。您应该继承tk.Tk而不是threading.Thread。不要为主循环创建函数,只需将其插入run()函数的底部(使用self而不是self.wbar)。在run()函数开始时初始化线程。在main()函数中,您已经调用了start,但是在类中,您将它定义为run()。下面是您的代码,如果您添加了上述更改并修复了所有错误:

代码语言:javascript
复制
import threading
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
from tkinter import Button
from tkinter import Label
import sys
import time

class tkwindow(tk.Tk):
    def __init__(self):
        super().__init__()
        
    def run(self):
        threading.Thread.__init__(self, daemon=True)
        self.attributes("-topmost", True) 
        self.title('Tool')
        lb=Label(self, text='Check in progress')
        lb.pack()
        pbar = ttk.Progressbar(self, orient='horizontal', length=500, mode='indeterminate')
        pbar.pack(pady=25)
        pbar.start(50) 
        self.protocol("WM_DELETE_WINDOW", self.on_closing)
        self.mainloop()
    
    def quitall(self):
        self.quit()
        sys.exit()
      
    def on_closing(self):
        if messagebox.askokcancel("Quit", "Do you want to quit?"):
          self.quitall()       

def main(): 
    mygui=tkwindow()     
    mygui.run()
    addit(2,3)
    
    mygui.quitall()

def addit(a,b):
    time.sleep(3)
    print(a+b)
    return

if __name__=='__main__':  
    main()

没有办法将进度条放入线程中。即使可以,它也不会有任何用处,因为它会使代码变得非常复杂。所以就用这个代替吧。

更新代码

代码语言:javascript
复制
import threading
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
from tkinter import Button
from tkinter import Label
import sys
import time

class tkwindow(tk.Tk):
    def __init__(self):
        super().__init__()
        
    def run(self):
        threading.Thread.__init__(self, daemon=True)
        self.attributes("-topmost", True) 
        self.title('Tool')
        lb=Label(self, text='Check in progress')
        lb.pack()
        pbar = ttk.Progressbar(self, orient='horizontal', length=500, mode='indeterminate')
        pbar.pack(pady=25)
        pbar.start(50) 
        self.protocol("WM_DELETE_WINDOW", self.on_closing)
    
    def quitall(self):
        self.quit()
        sys.exit()
      
    def on_closing(self):
        if messagebox.askokcancel("Quit", "Do you want to quit?"):
          self.quitall() 

def main(): 
    mygui=tkwindow()     
    mygui.run()
    addit(2,3)
    
    mygui.mainloop()
    
def addit(a,b):
    print("ADDIT")
    threading.Timer(3, lambda: print(a+b)).start()
    
if __name__=='__main__':  
    main()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74029524

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档