我在tkinter框架中使用ttk progessbar,当我在新线程中加载包含progressbar的框架时,我的GUI被冻结,但它似乎从主类运行良好,你能告诉我为什么会发生这种情况,我附上了以下代码。
import Tkinter as tk
import logging
from Tkinter import END, WORD
import threading
import time
class CardSystem(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
self.frames["StartPage"] = StartPage(container, self)
self.frames["StartPage"].grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
reader = threading.Thread(target=CardRead, args=(container, self, self.frames))
reader.daemon = True
reader.start()
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
boxFrame = tk.Frame(self, bg="Antique White")
boxFrame.grid(row=0, column=0, sticky="NSEW")
boxFrame.columnconfigure(0, weight=1)
boxFrame.rowconfigure(0, weight=1)
textbox = tk.Text(boxFrame, border="0", fg="black", bg="Antique White", wrap=WORD)
textbox.grid(row=0, column=0)
textbox.insert(END, "\n ttk progressbar in tkinter frames testing....")
textbox.config(state="disabled")
class LoaderPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
# progress_one = ttk.Progressbar(self)
# progress_one.grid(row=0, column=0, sticky="NEW")
# progress_one.start()
class CardRead(tk.Frame):
def __init__(self, parent, controller, frames):
tk.Frame.__init__(self, parent)
self.controller = controller
time.sleep(2)
frames["LoaderPage"] = LoaderPage(parent=parent, controller=controller)
frames["LoaderPage"].grid(row=0, column=0, sticky="nsew")
frames["LoaderPage"].tkraise()
if __name__ == "__main__":
app = CardSystem()
w = 900
h = 600
ws = app.winfo_screenwidth()
hs = app.winfo_screenheight()
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
app.geometry('%dx%d+%d+%d' % (w, h, x, y))
app.mainloop()
答案 0 :(得分:0)
您无法在多个线程中运行tkinter GUI代码。您需要在与所有其他GUI代码相同的线程中“加载框架”。您可以使用队列让工作线程请求GUI线程显示进度条。
答案 1 :(得分:0)
我找到了一个解决方案,认为这可能对某人有帮助,出于某种原因我们不能将ttk.progressbar放在由主线程以外的某个线程创建的框架中,在这种情况下我们使用progessbar的最佳选择是自己创建一个,我是使用以下代码完成的,
class LoaderPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.grid_rowconfigure(0)
self.grid_columnconfigure(0, weight=1)
globals()["progress"] = ProgressBar(self, height=25, width= ws)
globals()["progress"].grid(row=2, column=0, columnspan=3, sticky="EW")
for i in range(101):
globals()["progress"].set_value(i)
time.sleep(0.1)
class ProgressBar(tk.Canvas):
def __init__(self, master=None, **kw):
tk.Canvas.__init__(self, master, **kw)
self.width = float(self.config()["width"][-1]) + 2
self.height = float(self.config()["height"][-1]) + 2
self.value = 0
self.bar = self.create_rectangle(0, 0, self.width * self.value / 100., self.height, fill="dark green")
self.text = self.create_text(self.width / 2., self.height / 2., text=str(int(self.value)) + " %")
def set_value(self, value):
if 0 < value <= 100:
self.value = value
self.coords(self.bar, 0, 0, self.width * self.value / 100., self.height)
value = str(float(value))
self.itemconfig(self.text, text=str(value)[:str(value).index('.') + 3] + " %")
else:
raise ValueError, "0<value<=100"