当前位置: 首页 > 知识库问答 >
问题:

如何设置在单独线程上运行的tkinter textvariable?

宋建本
2023-03-14

正在尝试使用“main”函数变量更新线程上运行的tkinter“textvariable”。我实现了一个基于线程的解决方案,因此tkinter mainloop后面的代码可以运行:https://stackoverflow.com/a/1835036/15409926.

请分享我如何解决此错误。如果这不是更新“textvariable”的最简单方法,请分享其他方法。

代码:

from tkinter import *
from threading import Thread

class GUI(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.start()

    def run(self):
        self.root = Tk()
        self.var = StringVar()
        self.var.set("Initiated")

        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()

        width = screen_width*.12
        height = screen_height
        x = screen_width - width
        y = screen_height*.025

        self.root.geometry('%dx%d+%d+%d' % (width, height, x, y))

        label = Label(self.root, textvariable= self.var)
        label.pack()

        self.root.mainloop()

gui = GUI()

def main():
    for i in range(1000):
        gui.var.set(f'Current Iteration: {i}')

if __name__ == '__main__':
    main()

窗口不更新:Tkinter窗口显示初始“textvariable”

错误:

Traceback (most recent call last):
  File "test.py", line 36, in <module>
    main()
  File "test.py", line 33, in main
    gui.var.set(f'Current Iteration: {i}')
AttributeError: 'GUI' object has no attribute 'var'

共有1个答案

高砚
2023-03-14

大多数GUI不喜欢在单独的线程中更改小部件中的值。

你应该使用队列向线程发送值,它应该使用root.after(时间,函数)来定期运行函数,该函数将从队列中获取值并在GUI中更新值。

import tkinter as tk  # PEP8: `import *` is not preferred
from threading import Thread
import queue
import time  # simulate show program

class GUI(Thread):
    
    def __init__(self, queue):
        super().__init__()
        self.queue = queue
        self.start()

    def run(self):
        self.root = tk.Tk()
        self.var = tk.StringVar()
        self.var.set("Initiated")

        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()

        width = int(screen_width*.12)
        height = int(screen_height)
        x = int(screen_width - width)
        y = int(screen_height*.025)

        self.root.geometry(f'{width}x{height}+{x}+{y}')

        label = tk.Label(self.root, textvariable=self.var)
        label.pack()
 
        # run first time after 100ms (0.1 second)
        self.root.after(100, self.check_queue)

        self.root.mainloop()

    def check_queue(self):
        #if not self.queue.empty():
        while not self.queue.empty():
            i = self.queue.get()
            self.var.set(f'Current Iteration: {i}')

        # run again after 100ms (0.1 second)
        self.root.after(100, self.check_queue)
        
def main():
    q = queue.Queue()
    gui = GUI(q)

    for i in range(1000):
        q.put(i)
        # simulate show program
        time.sleep(0.5)


if __name__ == '__main__':
    main()

PEP 8-Python代码的风格指南

 类似资料:
  • 当我调用foo()时,这个方法是否在单独的线程上运行?

  • null 大多数文档描述了如何在Kubernetes上运行Spark集群。在Kubernetes上独立运行Spark的方法是什么?

  • 问题内容: 我设置了PhantomJS并将其录制到视频中:https : //www.dailymotion.com/video/xnizmh_1_webcam 生成说明:http : //phantomjs.org/build.html 我的设置有什么问题吗? 设置好之后,我阅读了快速入门教程并尝试编写此代码 它给我“找不到命令”错误。我怎么解决这个问题? 问题答案: Guidouil的回答使我

  • 问题内容: 我有一个正在运行的线程,但是从外面我无法绕过一个值来停止该线程。如何在内部发送false / true值或调用运行线程的公共方法?当我按下按钮1?例如: 或 跟进(校对): 问题答案: 如果您通过类而不是通过a定义它,则可以调用实例方法。 还要注意,由于多个内核具有自己的关联内存,因此您需要警告处理器该状态可能在另一个处理器上更改,并且它需要监视该更改。听起来很复杂,但只需将’vola

  • 我有一些HTML元素,它们都有相同的标记。每个div都有一个唯一的父类。 因此,当我尝试编写一些jQuery来单独针对每个元素时,它会在所有实例上触发,而不管我是否指定要针对哪个类。我的想法是,通过使用(this)它将只针对div“box__wrapper-before”中的内容。 有人知道我错在哪里吗? null null Codepen示例:https://Codepen.io/nickels

  • 我有一个单独的线程在后台运行在C中,我希望它能够发布代码,在另一个已经运行android的线程上运行。操作系统。活套(例如主线)。我所说的“post”是指类似于视图post的东西,其中可运行的排队在事件循环上运行。将要执行的代码也用C编写。 我找到了ALooper API(http://developer.android.com/ndk/reference/group___looper.html)