如何在python 2.7中使用tkk进度条和tkinter框架?

时间:2017-05-19 10:04:23

标签: python-2.7 tkinter

我在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()

2 个答案:

答案 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"