简体   繁体   English

在 Python TkInter 中更新标签文本

[英]Update Label Text in Python TkInter

Is there any possible way to create a TkInter label that uses a string and a variable as the text?是否有任何可能的方法来创建使用字符串和变量作为文本的 TkInter 标签?

For example:例如:

name = "bob"
Label(root, text="hello, my name is "+name)

But instead of that only making the text of the label to the above on label creation, to have it update the text when "name" changes without having to reference the label instance itself.但是,与其仅在创建标签时将标签文本设为上述内容,还不如在“名称”更改时更新文本,而无需引用标签实例本身。

Does anyone know if this is possible?有谁知道这是否可能?

You must tell the label to change in some way.你必须告诉标签以某种方式改变。

Here you have an example.这里有一个例子。 The text of the label is a textvariable text defined as a StringVar which can be changed whenever you want with text.set() .标签的text定义为StringVar text变量text ,可以随时使用text.set()进行更改。
In the example, when you click the checkbox, a command change tells the label to change to a new value (here simplified to take two values, old and new )在示例中,当您单击复选框时,命令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()

You cannot do precisely what you ask -- you can't associate both a static string and a variable to a label at the same time.您不能完全按照您的要求去做——您不能同时将静态字符串和变量与标签相关联。 There are things you can do to get the desired effect, but all you're doing is adding complexity with no real gain.您可以采取一些措施来获得所需的效果,但您所做的只是增加了复杂性而没有真正的收益。 For example, you can assign an instance of StringVar to the textvariable attribute of the Label widget.例如,您可以将StringVar的实例分配给Label小部件的textvariable属性。 When you do that, any update to the variable will update the label.当您这样做时,对变量的任何更新都会更新标签。 However, you end up having to make a function call to update the variable, so you don't really gain anything over making a function call to update the label directly.但是,您最终必须进行函数调用来更新变量,因此与进行函数调用以直接更新标签相比,您并没有真正获得任何好处。

Another option is to use two labels -- one for the static text and one for the variable.另一种选择是使用两个标签——一个用于静态文本,一个用于变量。 Put them side-by side with no border so the user won't notice.将它们并排放置,没有边框,这样用户就不会注意到。 Then, when you update the variable you'll get the desired effect.然后,当您更新变量时,您将获得所需的效果。 However, you're still having to make a function call to set the variable so you don't really gain much.但是,您仍然需要进行函数调用来设置变量,因此您并没有真正获得多少收益。

Yet another option is to use two instances of StringVar -- one for the label, and another for the name.另一种选择是使用StringVar两个实例——一个用于标签,另一个用于名称。 You can put a trace on the name variable so that when it changes, you automatically update the other variable with the static string and the value of the name variable, and that will cause the label to be automatically updated.您可以在 name 变量上放置一个跟踪,以便当它发生变化时,您会使用静态字符串和 name 变量的值自动更新另一个变量,这将导致标签自动更新。 Again, however, you're having to make a function call to put everything in motion然而,再次,您必须进行函数调用才能使一切都运转起来

So, as you can see, there are options, but they all add complexity to your code with no real gain over simply updating the label directly.因此,如您所见,有多种选择,但它们都增加了代码的复杂性,与直接更新标签相比并没有真正的好处。 The only time these other methods gain you an advantage is when the value needs to appear in more than one widget at once.只有当值需要一次出现在多个小部件中时,这些其他方法才能为您带来优势。 In that case you can associate the variable with two or more widgets, and a single function call will update all associated widgets.在这种情况下,您可以将变量与两个或多个小部件相关联,单个函数调用将更新所有关联的小部件。

Yes -- standard Tkinter < variable >-s mechanics does that:是的——标准 Tkinter < variable >-s 机制是这样做的:

There is a Tkinter StringVar() ( and similarly IntVar() , DoubleVar() , BoolVar() ) object constructor, that prepares a smart object that is ready to be later used for this very purpose in Tkinter Widgets.有一个 Tkinter StringVar() (以及类似的IntVar()DoubleVar()BoolVar() )对象构造函数,它准备了一个智能对象,准备好稍后在 Tkinter Widgets 中用于此目的。

You may use .set() / .get() methods for manipulating with such object's value(s).您可以使用.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

Label text gets changed right by a new value gets assigned in < variable >标签文本通过在 <变量> 中分配的新值而正确更改

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

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

You may also want to know about a more advanced tools for Tkinter variables.您可能还想了解更高级的 Tkinter 变量工具。 There are also more powerful tools associated with Tkinter variables -- called trace -er(s) -- which set the Tkinter system to "watch" any change to a "traced" variable and this can associate further automated responsive activities, automatically launched upon a traced-event-type.还有与 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()

This instrumentation helps you create your GUI toolbox strategies very powerful for an efficient, event-driven, fully self-reflecting layered [Model-Visual-Controller], supervised under the hood of the Tkinter.mainloop() scheduler该工具可帮助您创建非常强大的 GUI 工具箱策略,用于高效、事件驱动、完全自反射的分层 [模型-视觉-控制器],在Tkinter.mainloop()调度程序的引擎盖下进行监督

How to put it together?如何把它放在一起?

As abarnert has proposed, the automated version may look in principle like this正如 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM