使用类和框架,tkinter在标题栏中获取应用程序“无响应”消息。需要多线程/处理帮助来解决

2024-05-19 13:08:12 发布

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

我是python/tkinter新手,运行python 3.8。我遇到一个问题,需要启动一个线程/进程,在CSF.addOrders处于活动状态时缓慢更新pb1(progressbar)。CSF.addOrders在服务器上运行,需要10秒到5分钟,具体时间取决于订单数量。它会导致应用程序显示“无响应”,即使它正在工作。此外,由于时间延迟,应用程序用户不知道程序仍在运行,因为progressbar(pb1)没有更新

我简化了用于显示关键段的代码。我需要pb1(progressbar)在CSF.addOrders运行时缓慢更新,并在CSF.addOrders完成后立即终止。我读过很多关于不回应的帖子,但我不知道该怎么办。因为使用了框架和类,所以似乎还没有给出答案。如有任何帮助/指导,将不胜感激

这是修复tkinter GUI“无响应”的代码,允许progressbar继续,直到服务器端功能完成。

import tkinter as tk
import tkinter.ttk  as ttk
import ClientServer_Functions as CSF
import threading
import queue
import logging
import time

# Log File
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S')

# create the handlers and call logger.addHandler(logging_handler)
if not logger.handlers:
    file_handler = logging.FileHandler('GUI_Logger.log')
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(formatter)

    stream_handler = logging.StreamHandler()
    stream_handler.setFormatter(formatter)

    logger.addHandler(file_handler)
    logger.addHandler(stream_handler)

logger.propagate = False

class sample(tk.Tk):   
    def __init__(self):
        tk.Tk.__init__(self)
        self.shared_data = {
            "fName": tk.StringVar(),  # userInfo[0][0] 
            "username": tk.StringVar(),  # userInfo[0][1]
            "password": tk.StringVar(),  # userInfo[0][2]
            "custSym": tk.StringVar(),  # userInfo[0][3]
            "email": tk.StringVar(),  # userInfo[0][4]
            "sPath": tk.StringVar(),  # userInfo[0][5]
            "FTP_User": tk.StringVar(),  # userInfo[0][6]
            "FTP_Password": tk.StringVar(),   # userInfo[0][7]
            "fType": tk.StringVar()
            }
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        
        global bgColor
        bgColor = "black"
        self.frames = {}
        for F in (Trade, blank): #there are other frames I create that are not listed
            frame = F(container, self)
            self.frames[F] = frame
            frame.config(bg=bgColor)
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(Trade)

    def get_page(self, page_class):
        return self.frames[page_class]
    
    def show_frame(self, c):
        frame = self.frames[c]
        frame.tkraise()
        
class Trade(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller=controller
        
        tk.Label(self, bg=bgColor).pack()
        tk.Label(self, text="TRADES", bg=bgColor, fg="yellow").pack(pady=20)
        tk.Button(self, text="Orders", command=lambda: [self.setFType("Orders"), self.files()]).pack(pady=10)
        self.statusbar = tk.Label(self)
        self.statusbar.pack(side=tk.BOTTOM, fill=tk.X)
    
    def setFType(self, fType):
        self.controller.shared_data["fType"].set(fType)    
    
   
    def aOrders(self, ls):
        l = ls[0]
        print("starting t1")
        time.sleep(1)
        result, msg, FTP_outFile = CSF.addOrders(l,"u", "p", "fp", "sp", "c") 
        return result, msg, FTP_outFile
        
   
    def files(self): 
        fType = self.controller.shared_data["fType"].get()
        self.statusbar['text'] = "Running..."
        pb1 = ttk.Progressbar(self, orient=tk.HORIZONTAL, length=250, mode='determinate')
        pb1['value'] += 10
        pb1.place(relx=.25, rely=.88)
        
        que = queue.Queue()
        t1 = threading.Thread(target = lambda q, arg : q.put(self.aOrders(arg)), args = (que, [logger, 2]))
        t1.start()
        for x in range(100):
            if t1.is_alive():
                print("update pb1")
                pb1['value'] += 2
                tk.Tk.update(self)
                time.sleep(1)
            else:
                print(que.get())
                break
        print("do balance of program...")

class blank(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller=controller 
        
if __name__ == "__main__":
    app = sample()
    app.geometry("500x500+500+150")
    app.mainloop()

Tags: importselfinitloggingdefloggerframetk
1条回答
网友
1楼 · 发布于 2024-05-19 13:08:12

您的代码将在此处被阻止:

t1 = threading.Thread(target=self.aOrders(u, p, fp, sp, c))

这只是执行函数并等待它退出。试一试

t1 = threading.Thread(target=self.aOrders, args=(u, p, fp, sp, c))

相反。不确定这是否是您的程序的唯一问题,但这是显而易见的问题

相关问题 更多 >