python - 使用类和框架与 tkinter 在标题栏中获取应用程序“无响应”消息。需要多线程/处理帮助来解决
问题描述
我是 python/tkinter 的新手,正在运行 python 3.8。我遇到了一个问题,我需要启动一个线程/进程,该线程/进程将在 CSF.addOrders 处于活动状态时缓慢更新 pb1(progressbar)。CSF.addOrders 在服务器上运行,需要 10 秒到 5 分钟,具体取决于订单数量。即使它正在运行,它也会导致应用程序显示“无响应”。此外,时间延迟使得应用程序用户不知道程序仍在运行,因为进度条(pb1)没有更新。
我已经简化了用于显示关键部分的代码。我需要 pb1(progressbar) 在 CSF.addOrders 运行时缓慢更新,并在 CSF.addOrders 完成后立即终止。我已经阅读了很多关于 Not Responding 的帖子,但一直无法弄清楚该怎么做。由于使用了框架和类,它似乎还没有提供答案。任何帮助/指导将不胜感激。
这是修复 tkinter GUI“无响应”的代码,并允许进度条继续,直到服务器端功能完成。
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()
解决方案
您的代码将在这里阻塞:
t1 = threading.Thread(target=self.aOrders(u, p, fp, sp, c))
这只是执行函数并等待它退出。尝试
t1 = threading.Thread(target=self.aOrders, args=(u, p, fp, sp, c))
反而。不确定这是否是您的程序存在的唯一问题,但这是显而易见的问题。
推荐阅读
- docker - ADD 和 COPY Dockerfile 指令有什么区别?
- c# - 尝试强制转换空值时抛出异常
- node.js - 应该如何为 Node.js docker 应用生成 package-lock.json 文件?
- sql - 收集集的续集替代解决方案
- json - Spark:将 JSON 加载为 DataFrame 的正确模式
- css - SASS/SCSS - 制作一个将“退出”以修改选择器父级的选择器
- sorting - 排序键似乎没有正确计算 utf8 字符
- python - Python LDAP3一次在多个search_base中搜索
- java - spring-session 是否使用 HttpSession 保存 bean?
- python - 使用递归反转单链表