【问题标题】:Tkinter label textvariable does not track StringVar while thread updates itTkinter 标签文本变量在线程更新时不跟踪 StringVar
【发布时间】:2020-07-26 12:20:11
【问题描述】:

已编辑:将问题简化为可重现的最小示例。

我正在制作一款闲置游戏,因此我希望在游戏窗口中跟踪当前的金额和每秒的当前收入。我正在使用 tkinter 创建 GUI,并在单独的守护线程中进行收入计算。

当我启动游戏并购买单位时,他们会按预期添加资金并按预期跟踪当前余额。我检查了收入变量 (tk.IntVar()) 并确认它也已正确更新为当前收入。

但是,跟踪余额的 tkinter 标签会正确更新,而income/s 标签会。它始终保持在“0/s”。

这里是代码,简化为包括一个单元和购买它们的选项:

import time
import threading
import tkinter as tk

window = tk.Tk()
window.title("test")

class Currency:
    """For objects that track currency stashes and income."""

    def __init__(self, currency_name, currency_type):
        self.name = currency_name
        self.value = tk.IntVar(window, 0)
        self.income = tk.IntVar(window, 0)
        self.type = currency_type
        self.lbl_name = tk.Label(window,
                                 text=("{0}:".format(self.name)),
                                 justify=tk.LEFT)
        self.lbl_value = tk.Label(window, textvariable=self.value)
        self.lbl_income = tk.Label(window,
                                   textvariable=tk.StringVar(window,
                                                             str(self.income.get())+"/s"),
                                   justify=tk.RIGHT)
"""
The label I have a problem with.
"""


unit_list = []
influence = Currency(
    'Influence',
    'influence')


class IncomeUnit:
    """For sources of passive income"""

    def __init__(self, name, base_inc, unit_type, cost_type):
        self.name = name
        self.inc = base_inc
        self.number = tk.IntVar(window, 0)
        self.type = unit_type
        self.cost_type = cost_type
        self.lbl_name = tk.Label(window, text=("{0}:".format(self.name)),
                                 justify=tk.LEFT)
        self.lbl_number = tk.Label(window, textvariable=self.number)
        unit_list.append(self)
        self.buysell_1 = tk.Button(window, text="1", command=self.buy)

    def buy(self):  # implement subtracting costs
        self.number.set(self.number.get() + 1)


stitched = IncomeUnit(
    'Stitched',  # Name of the unit
    1,  # Base income of the unit
    'influence',
    'research'
    )

influence.lbl_name.grid(column=0, row=1)
influence.lbl_value.grid(column=1, row=1)
influence.lbl_income.grid(column=0, row=2)

top_rows = 6  # Change when you add more stuff on top. Rearranges unit grid.
for i in range(len(unit_list)):
    unit_list[i].lbl_name.grid(column=0 if i < 8 else 6,
                               row=i * 2 + top_rows if i < 8 else (i - 8) * 2 + top_rows,
                               sticky=tk.W)
    unit_list[i].lbl_number.grid(column=1 if i < 8 else 7,
                                 row=i * 2 + top_rows if i < 8 else (i - 8) * 2 + top_rows,
                                 sticky=tk.W)
    unit_list[i].buysell_1.grid(column=2 if i < 8 else 8,
                                row=i * 2 + top_rows if i < 8 else (i - 8) * 2 + top_rows,
                                sticky=tk.W)

def allincome():
    while True:
        temp_inc = 0
        for un in range(len(unit_list)):
            if unit_list[un].type == influence.type:
                influence.value.set(influence.value.get() +
                                    unit_list[un].inc *
                                    unit_list[un].number.get())
            temp_inc += unit_list[un].inc * unit_list[un].number.get()
            influence.income.set(temp_inc)
        print(temp_inc)
"""Prints the correct value"""
        print(influence.income.get())
"""Prints the correct value"""
        time.sleep(1)


income_thread = threading.Thread(None, allincome, daemon=True)
income_thread.start()


window.mainloop()

这个循环计算每秒的收入,并用当前数据更新标签变量。

我是否遗漏了阻止 self.lbl_income 更新的内容?

【问题讨论】:

  • 请尝试将所有代码缩减为minimal reproducible example
  • @BryanOakley 更新了问题。不确定在澄清问题后@是否是一种好习惯,如果不是,抱歉。
  • 使用 @ 是我们获得通知的方式,否则我们不会收到 cmets 的通知 :)

标签: python multithreading tkinter


【解决方案1】:

我找到了解决办法。经过一些实验,我发现textvariable只有直接设置为:

textvariable=self.income

,同时定义

self.income = tk.StringVar(window, '0/s')

并将其更新为

influence.income.set(str(temp_inc)+'/s')

【讨论】:

    猜你喜欢
    • 2020-11-26
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-15
    • 2011-02-05
    • 1970-01-01
    相关资源
    最近更新 更多