首页 > 解决方案 > tkinter 实时数据标签更改(取决于用户输入)

问题描述

所以我正在尝试编写一个中世纪的 RPG,我正在使用 Tkinter 来显示用户的健康、耐力、控制等。我正在努力让用户的基本耐力为 50,如果他们按下点击“攻击”按钮,体力会减少5,随着时间的推移慢慢恢复,(如果当前STM低于50,它开始每毫秒增加1点,直到再次达到50)。每次按下“攻击”时,减法都会起作用,但我似乎根本无法让我的if (stamina < stmmax):陈述起作用。有小费吗?

import time
import sys
import random as rand
from tkinter import *

# -----------------------------------Custom Functions---------------------------------------

def dramaticeffect():
    time.sleep(2)
    print("")

def delay_print(s):
    for c in s:
        sys.stdout.write(c)
        sys.stdout.flush()
        time.sleep(0.1)
    time.sleep(1)
    print("")

def die():
    delay_print("Your adventure has ended, " + name + ".")
    sys.exit()

def endprogress():
    print("[This is the end of the game's current progress]")
    die()

def actionlog():
    global log
    log = log + 1
    action = True
    print("\t inputlog#" + str(log))
    logcheck.configure(text="*")

def attack():
    global stamina
    stamina = int(stamina - 5)
    print(stamina)
    stmcount = ("Stamina: " + str(stamina) + "/" + str(stmmax))
    stmmeter.configure(text=stmcount)
    live = True
    actionlog()

'''
def uistart():
    window = Tk()
    window.title("Fate of all")
    uidefault()

def uidefault():
    label = Label(window, text="Testing")
    entry = Entry(window)
    button1 = Button(window, text="Enter")
    button2 = Button(window, text="SB_1")
    button3 = Button(window, text="SB_2")

def uihalt():
    label.pack()
    entry.pack()
    button1.pack()
    button2.pack()
    button3.pack()

    window.mainloop()
'''

# ---------------------------------------Gameplay-------------------------------------------

window = Tk()
window.title("Fate of all")

log = int(0)

live = False

stmmod = int(0)
stamina = int(50 + stmmod)
stmmax = int(50 + stmmod)

if (stamina < stmmax):
    time.sleep(0.1)
    stamina = stamina + 1
    print(stamina)

stmcount = ("Stamina: " + str(stamina) + "/" + str(stmmax))

#damage

stmmeter = Label(window, text=stmcount)
entry = Entry(window)
button1 = Button(window, text="Enter", command=actionlog)
button2 = Button(window, text="Attack", command=attack)
button3 = Button(window, text="Defend", command=actionlog)
logcheck = Label(window, text="")

stmmeter.pack()
entry.pack()
button1.pack()
button2.pack()
button3.pack()
logcheck.pack()

window.mainloop()



#name = input("This is the tale of... ")

#dramaticeffect()

#delay_print('''
#Greetings, Sir ''' + name + ''', I am a humble traveler like you. Allow me to tell you a
#story, a tale of a friend or two.
#''')

#delay_print('''
#\t It is a desolate time, there are wars between sword and stone all
#across the land...and you were but a simple knight trying to survive,
#but everything changed once you entered the outer lands of Newlochia.
#''')

#delay_print("Fate of all is in your hands.")

#dramaticeffect()

标签: pythonpython-3.xuser-interfacetkinter

解决方案


首先,当您在 Tk 实例中有 if 语句时,显然它只会运行一次,其次,time.sleep(some_num)与 GUI 应用程序一起使用不是一个好主意,因此最好root.after(millis, func)在函数中使用和使用它。它还取决于您希望何时何地运行您的函数。如果您希望它在角色受到攻击时运行,那么您可以执行以下操作并将其绑定到按钮或在已绑定到您的按钮的其他函数中调用它:

def regenerate():
    global stamina
    if stamina < stmmax:
        stamina += 1
        root.after(60, regenerate)
        # root.after works with millis so it is better to use
        # a bigger number like 60 rather than 1

更新:我尝试实现您的代码,我相信这更有可能是您想要的:

from tkinter import *


root = Tk()
root.title("Game!")
root.geometry("400x300")
stamina, stmmax = 50, 50
regenerating = False
lbl = Label(root, text=f"Stamina: {stamina}")
lbl.pack(pady=15)


def regenerate():
    global regenerating
    if not regenerating:
        regenerating = True

        def add_stamina():
            global stamina, regenerating
            if stamina < stmmax:
                stamina += 1
                lbl.config(text=f"Stamina: {stamina}")
                root.after(100, add_stamina)
            else:
                regenerating = False

        add_stamina()

def attack():
    global stamina
    stamina -= 15
    lbl.config(text=f"Stamina: {stamina}")
    regenerate()

Button(root, text="Attack!", command=attack).pack()
root.mainloop()

我还尝试使用while True: (smth)循环编写函数并使用threading.Thread不断检查当前耐力是否小于最大耐力,但似乎在每次试验中代码都失败并且 GUI 冻结。尽管仅使用普通功能是更好的方法。

更新:很抱歉有很多更新。考虑到代码我不满意,因为它不是很干净,所以为了优化我做了一个更好的版本。同样在您配置标签很多的情况下,我宁愿为标签设置一个文本变量。没有文本变量的代码:

from tkinter import *


root = Tk()
root.title("Game!")
root.geometry("400x300")
stamina, stmmax = 50, 50
regenerating = False
lbl = Label(root, text=f"Stamina: {stamina}")
lbl.pack(pady=15)

def add_stamina():
    global stamina, regenerating
    if stamina < stmmax:
        stamina += 1
        lbl.config(text=f"Stamina: {stamina}")
        root.after(100, add_stamina)
    else:
        regenerating = False

def attack():
    global stamina, regenerating
    stamina -= 15
    lbl.config(text=f"Stamina: {stamina}")
    if not regenerating:
        regenerating = True
        add_stamina()

Button(root, text="Attack!", command=attack).pack()
root.mainloop()

与文本变量相同的代码:

from tkinter import *


root = Tk()
root.title("Game!")
root.geometry("400x300")
stamina, stmmax = 50, 50
regenerating = False
stm_var = StringVar()
stm_var.set(f"Stamina: {stamina}")
lbl = Label(root, textvariable=stm_var)
lbl.pack(pady=15)

def add_stamina():
    global stamina, regenerating
    if stamina < stmmax:
        stamina += 1
        stm_var.set(f"Stamina: {stamina}")
        root.after(100, add_stamina)
    else:
        regenerating = False

def attack():
    global stamina, regenerating
    stamina -= 15
    stm_var.set(f"Stamina: {stamina}")
    if not regenerating:
        regenerating = True
        add_stamina()

Button(root, text="Attack!", command=attack).pack()
root.mainloop()

推荐阅读