首页 > 解决方案 > 如何在 Tkinter 中显示对类对象的每一次更改?

问题描述

我在两个文件中有这个游戏的骨架。

第一个文件mygui.py

from tkinter import Tk, Label, Button
from mygame import p1, play_game

def rungame():
    play_game()
    gui_widgets()

root = Tk()

def gui_widgets():
    health_label = Label(root, text=f"health: {p1.health}")
    health_label.grid(column=0, row=0)

    mana_label = Label(root, text=f"mana: {p1.mana}")
    mana_label.grid(column=0, row=1)

    mybtn = Button(root, text="RUN GAME", command=rungame)
    mybtn.grid(column=0, row=2)

gui_widgets()
root.mainloop()

第二个文件mygame

import time

class Player:

    def __init__(self, health, mana):
        self.health = health
        self.mana = mana

def play_game():
    p1.health -= 1
    time.sleep(0.5)
    p1.mana -= 3
    time.sleep(0.5)
    p1.mana += 1

p1 = Player(10, 15)

游戏在 gui 上显示开始统计数据,单击按钮后显示最终结果。我希望 gui 显示p1发生时所做的每一个属性更改play_game()。我该怎么做?

编辑:我热衷于保留两个单独的文件,以便该程序更具可扩展性。

我不确定这是否可能,但我想如果我可以gui_widgets()连续运行(例如每 0,1 秒)它可能会按预期工作。我仍然明白这可能是不可能的,因为 tkinter 似乎每次play_game()运行时都在等待,女巫至少需要一秒钟才能完成。因此,在这种情况下,他们可能应该彼此并肩运行(如果那是一件事的话)。

标签: pythontkinter

解决方案


可能有很多方法。

这是一种方法

  • 定义__setattr__向缓冲区发送信号以更新 GUI 的方法。
  • sleep在主线程中可能会阻止您的 GUI 更新,所以这里使用了另一个线程。
  • 从缓冲区内容刷新/更新 GUI 的固定且短的计时器。
# mygui.py
import threading
from tkinter import Tk, Label, Button

from mygame import p1, play_game, buffer


def rungame():
    threading.Thread(target=play_game, args=(), daemon=True).start()

def update():

    if buffer:
        attribute, value = buffer.pop(0)
        if attribute == 'health':
            health_label.configure(text=f"health: {value}")
            health_label.update()
        elif attribute == 'mana':
            mana_label.configure(text=f'mana: {value}')
            mana_label.update()
    root.after(100, update)

def gui_widgets():

    health_label = Label(root, text=f"health:", width=20)
    health_label.grid(column=0, row=0)
    mana_label = Label(root, text=f"mana:", width=20)
    mana_label.grid(column=0, row=1)
    mybtn = Button(root, text="RUN GAME", command=rungame)
    mybtn.grid(column=0, row=2)
    return health_label, mana_label

root = Tk()

health_label, mana_label = gui_widgets()

root.after(100, update)
root.mainloop()
#my game.py
import time

class Player(object):

    def __init__(self, health, mana):
        self.health = health
        self.mana = mana

    def __setattr__(self, attribute, value):
        super().__setattr__(attribute, value)
        buffer.append((attribute, value))

def play_game():

    for i in range(10):
        p1.health = i
        time.sleep(0.2)
        p1.mana = 9 - i
        time.sleep(0.2)

buffer = []
p1 = Player(10, 15)

推荐阅读