Update Label Text in Python TkInter

前端 未结 3 1322
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-07 10:47

Is there any possible way to create a TkInter label that uses a string and a variable as the text?

For example:

name = \"bob\"
Label(root, text=\"hel         


        
相关标签:
3条回答
  • 2021-01-07 11:03

    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. 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. 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. 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.

    0 讨论(0)
  • 2021-01-07 11:13

    Yes -- standard Tkinter <variable>-s mechanics does that:

    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.

    You may use .set() / .get() methods for manipulating with such object's value(s).

    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

    You may also want to know about a more advanced tools for Tkinter variables. There are also more powerfull 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.

    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 powerfull for an efficient, event-driven, fully self-reflecting layered [Model-Visual-Controller], supervised under the hood of the Tkinter.mainloop() scheduler

    How to put it together?

    As abarnert has proposed, the automated version may look in principle like this

    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
    
    0 讨论(0)
  • 2021-01-07 11:17

    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().
    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)

    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()
    
    0 讨论(0)
提交回复
热议问题