Search code examples
variablesscopetcltk-toolkit

Failed to create dynamic variable


I'm trying to create the same numbered variable, but there's something that stops it. But I haven't figured out what it could be yet.

i.e.

set txt0 ""
set txt1 ""
set txt3 ""

So I'm trying to do this dynamically with every click on the button. See my code:

frame .top.tab

button .top.tab.btnTab -text "+" -command { bell ; add }

frame .top.tool
.top.tool configure -relief "raised"

frame .top.panel
.top.panel configure -bg "white"

set n 0

proc add {} {

    global n

    set txt$n ""

        entry .top.tool.ent$n -textvar txt$n

        button .top.tool.btn$n -text txt$n -command " remove $n ; .top.panel.lbl$n config -textvar $txt$n "

        pack .top.tool.ent$n .top.tool.btn$n -side left
incr n
        label .top.panel.lbl$n -text "" -bg "white"

        pack .top.panel.lbl$n -fill both -expand yes -anchor e

}

pack .top.tab -side top -fill x -anchor nw
pack .top.tab.btnTab -side right

proc remove { number } {    

    set total 2

    for { set i 0 } { $i < $total } { incr i } {                    
                    
        pack forget .top.panel.lbl$i
        
    }
    
    pack forget .top.panel.lbl$total
        
    pack .top.panel.lbl$number -fill both -expand yes -anchor e
}

pack .top.tool -side top -fill x -anchor nw
pack .top.panel -side top -fill both -expand yes -anchor sw

What could it be?

I know this around the variable $txt$n


Solution

  • You're creating a local variable with the name you want, but Tk won't bind anything to local variables as widgets typically outlast stack frames. You also want to be careful about when you are dealing with the name of a variable versus the current content of the variable.

    In the simple case, the best approach is to use an element of a global array:

    proc add {} {
        global n txt
    
        set txt($n) ""
    
        entry .top.tool.ent$n -textvar txt$n
        button .top.tool.btn$n -text txt$n -command \
            " remove $n ; .top.panel.lbl$n config -textvar txt($n) "
        pack .top.tool.ent$n .top.tool.btn$n -side left
        
        incr n
        
        label .top.panel.lbl$n -text "" -bg "white"
        pack .top.panel.lbl$n -fill both -expand yes -anchor e
    }
    

    In more complex cases, consider using a TclOO object to hold the state; handles to those are usually "simple" words (unless you take special steps to make them not be; most programmers simply aren't that devious normally).