使用线程更新Tkinter GUI

时间:2019-12-04 22:57:05

标签: python python-3.x multithreading tkinter

我正在研究一个遵循基本结构的项目:一个音序器类实例化一个GUI类,该类提供了更新/修改GUI上的内容的功能(更改背景图像,更新文本字段等)。在音序器类中,我想启动一些方法response.xpath('//tag1 | //tag2').getall() ,该方法执行一些操作(包括一些run_test命令,并更新GUI以显示测试正在运行。显然,GUI主循环冻结了。发生这种情况且GUI无法更新时。

什么是正确的解决方案?如何在另一个线程中启动run_test以便GUI可以更新?

time.sleep()

结果是代码休眠5秒钟,然后GUI更新了背景图像。我希望它立即发生,并可能在run_test期间发生各种情况时动态发生(例如,取决于run_test的通过/失败,在GUI上显示不同的内容)。

我该怎么做?!

1 个答案:

答案 0 :(得分:0)

我这里有一些代码可能会对您有所帮助。我已经遇到过您的问题,并且通过线程化另一个将运行我的代码的类来解决。因此,很遗憾,我无法显示完整的代码,但我尝试为您提供一些帮助。

DELAY = 100  # millisecs between status label updates

# global flag and a Lock to control concurrent access to it
run_flag_lock = threading.Lock()
running = False

class RunningClass(threading.Thread):
    def __init__(self):
        self.run()

    def run(self):
        global running
        # random work
        YOUR CODE
        with run_flag_lock:
            running = False

class GUI(Frame, object):
    def __init__(self, master)
        super(GUI, self).__init__(master)
        global running
        self.button = Button(self, text="EXECUTE", command=lambda: self.execute(), bg="green", fg='white')
        self.button.grid(row=0, column=0, sticky=E + W)
        with run_flag_lock:
            running = False
        self.after(DELAY, self.update_status, None)  # start status widget updating

    def update_status(self, run_state):
        global running
        """ Update status label text and state of buttons to match running flag. """
        # no need to declare run_flag_lock global since it's not being assigned a value
        with run_flag_lock:
            if running != run_state:  # status change?
                if running:
                    run_state = True
                else:
                    run_state = False
            else:
                try:
                    x = self.temp
                except:
                    pass
        # run again after a delay to repeat status check
        self.after(DELAY, self.update_status, run_state)


    def execute(self):
        global running
        flag_error = False
        with run_flag_lock:
            if not running:
                self.temp = RunningClass()
                self.temp.start()
                running = True

if __name__ == '__main__':
    ROOT = Tk()
    ROOT.title("TEXT")
    LOGIN = GUI(ROOT)
    LOGIN.grid(sticky=E)
    ROOT.mainloop()