在 Python TkInter 中更新标签文本

Dóu*_*lax 5 python tkinter

有没有可能的方法来创建使用字符串和变量作为文本的 TkInter 标签?

例如:

name = "bob"
Label(root, text="hello, my name is "+name)
Run Code Online (Sandbox Code Playgroud)

但不是仅在创建标签时将标签文本设置为上述内容,而是在“名称”更改时更新文本,而不必引用标签实例本身。

有谁知道这是否可能?

joa*_*uin 8

您必须告诉标签以某种方式进行更改。

这里有一个例子。标签的文本是一个text定义为 的文本变量StringVar,可以随时使用 进行更改text.set()
在示例中,当您单击复选框时,命令change会告诉标签更改为新值(此处简化为采用两个值,oldnew

from Tkinter import Tk, Checkbutton, Label
from Tkinter import StringVar, IntVar

root = Tk()

text = StringVar()
text.set('old')
status = IntVar()

def change():
    if status.get() == 1:   # if clicked
        text.set('new')
    else:
        text.set('old')


cb = Checkbutton(root, variable=status, command=change)
lb = Label(root, textvariable=text)
cb.pack()
lb.pack()

root.mainloop()
Run Code Online (Sandbox Code Playgroud)


use*_*197 5

是的——标准 Tkinter <variable> -s 机制可以做到这一点:

有一个 Tkinter StringVar()(以及类似的IntVar(), DoubleVar(), BoolVar())对象构造函数,它准备一个智能对象,以便稍后在 Tkinter Widgets 中用于此目的。

您可以使用.set()/.get()方法来操作此类对象的值。

name              = StringVar()        # this creates a Tkinter object
name.set( "bob" )                      # .set() assigns / .get() retrieves
L = Label( root, textvariable = name ) # makes the <name> used in Label Widget
Run Code Online (Sandbox Code Playgroud)

标签文本会通过在<variable>中分配的新值而更改

name.set( "alice" )                    # .set() assigns a new value -> promoted
print L['text']                        # show, a value has been promoted in L
Run Code Online (Sandbox Code Playgroud)

仅供参考:高级<变量>-s'工具

您可能还想了解 Tkinter 变量的更高级工具。还有与 Tkinter 变量相关的更强大的工具 - 称为trace-er(s) - 将 Tkinter 系统设置为“监视”对“跟踪”变量的任何更改,这可以关联进一步的自动化响应活动,自动启动跟踪事件类型。

aWriteTraceID = name.trace_variable( "w", f2CallOnWriteAccessToTracedVariable )
aRead_TraceID = name.trace_variable( "r", f2CallOnRead_AccessToTracedVariable )
aDel__TraceID = name.trace_variable( "u", f2CallOnDel__AccessToTracedVariable )

name.trace_vinfo()                        # show all associated <<Tracers>>

>>> name.trace_vinfo()
[('u', '12945528f2CallOnDel__AccessToTracedVariable'),
 ('r', '12251384f2CallOnRead_AccessToTracedVariable'),
 ('w', '12760924f2CallOnWriteAccessToTracedVariable')
]

name.trace_vdelete( aRead_TraceID )       # delete an identified <<Tracer>>
name.trace_vdelete( aWriteTraceID )       # delete an identified <<Tracer>>

del( name )                               # del() makes name undefined
# so this will "auto-launch" the last, still active <<Tracer>>
# you assigned above -- the function f2CallOnDel__AccessToTracedVariable()
Run Code Online (Sandbox Code Playgroud)

该工具可帮助您创建非常强大的 GUI 工具箱策略,以实现高效、事件驱动、完全自我反思的分层 [模型-视觉-控制器],并在调度程序的后台进行Tkinter.mainloop()监督

如何将它们组合在一起?

正如 abarnert 所提议的,自动化版本原则上可能如下所示

name = StringVar()                         # a pure name holder
show = StringVar()                         # a post-processed text

L = Label( root, textvariable = show )     # L will display a post-processed string
L.pack()                                   # L goes into GUI framework's geometry manager

#                                          # prepare the <<Handler>> function
def autoProcessAndPropagateOnNameVarCHANGE( p1, p2, p3, p4 = name, p5 = show ):
    #                                      # this function will get called
    #                                      # upon WRITE-ACCESS <<Tracer>>
    #
    # .set( a post-processed value ) into [show], that is connected to GUI[Label]
    p5.set( "Hello, " + p4.get() )         
    #                                      # Always be carefull not to fire
    #                                      # an unstoppable chain-reaction ;)
    #                                      # of <<Tracer>>-related events
    #                                      # as more <<Tracer>>-s get used

#                                          # create <<Tracer>> / <<Handler>> pair
aWriteTraceID = name.trace_variable( "w", autoProcessAndPropagateOnNameVarCHANGE )

# -------------------------------------------------------------------------------
# test <<Tracer>>:
name.set( "Craig" )                        # <<Tracer>>-watched WRITE-ACCESS
# test <<Tracer>> result: GUI Label L shall show "Hello, Craig" -----------------

# -------------------------------------------------------------------------------
# erase all <<Tracer>>-s assigned:
name.trace_vinfo()                         # initial state of <<Tracer>>-s

for aTracerRECORD in name.trace_vinfo():
    name.trace_vdelete( aTracerRECORD[0], aTracerRECORD[1] )

# erase [[[DONE]]] --------------------------------------------------------------
name.trace_vinfo()                         # final   state of <<Tracer>>-s
Run Code Online (Sandbox Code Playgroud)


Bry*_*ley 5

您无法精确地执行您所要求的操作 - 您无法同时将静态字符串和变量与标签相关联。您可以采取一些措施来获得所需的效果,但您所做的只是增加了复杂性,而没有真正的收获。例如,您可以将 的实例分配StringVar给小部件textvariable的属性Label。当您这样做时,对变量的任何更新都会更新标签。但是,您最终必须进行函数调用来更新变量,因此与直接进行函数调用来更新标签相比,您实际上并没有获得任何好处。

另一种选择是使用两个标签——一个用于静态文本,一个用于变量。将它们并排放置,没有边框,这样用户就不会注意到。然后,当您更新变量时,您将获得所需的效果。但是,您仍然需要进行函数调用来设置变量,因此您并没有真正获得太多好处。

另一种选择是使用两个实例StringVar——一个用于标签,另一个用于名称。您可以在 name 变量上进行跟踪,以便当它发生更改时,您可以使用静态字符串和 name 变量的值自动更新另一个变量,这将导致标签自动更新。然而,您必须再次调用函数才能使一切运转起来

因此,正如您所看到的,有一些选项,但它们都会增加代码的复杂性,并且比直接更新标签没有真正的好处。这些其他方法唯一为您带来优势的时候是当该值需要同时出现在多个小部件中时。在这种情况下,您可以将变量与两个或多个小部件关联,并且单个函数调用将更新所有关联的小部件。

  • @user3666197:我不知道你的评论想说什么。 (9认同)