2

I keep getting "bad window or path name" when trying to add the first button. And i do not have a clou why... I'm pretty shure to have used the same syntax elsewhere without problems...

tk::toplevel ".topbox"
wm title .topbox "SnapShooter"
wm geometry .topbox 200x200+0+0
wm resizable .topbox 0 0
button .topbox.btn_1  -text "Destroy"  -width 150 -background  green -command   [destroy .topbox ]                                                   
pack .topbox.btn_1                                                
button .topbox.btn_2  -text "Shoot Image"  -width 150 -background  green -command [ puts something]
pack  .topbox.btn_2
Lumpi
  • 2,697
  • 5
  • 38
  • 47
  • Have a look here: https://groups.google.com/forum/#!topic/comp.lang.tcl/i6LjeaPChlk as well as here: http://wiki.tcl.tk/15242 ; these were the first 2 results when I googled – Dexygen Jan 24 '14 at 14:57
  • Sorry, maybe i need more coffe: But my windowname starts with a "." and as a toplevel window I do not have to "pack" it either. By the way: I also found these two sites before i asked ;-) – Lumpi Jan 24 '14 at 15:03
  • It's ok, answers aren't really answers if they are just links, but I thought I could help you with the links if you hadn't found them, so I at least made the comment. – Dexygen Jan 24 '14 at 15:37

1 Answers1

3

Whenever you give a command, such as button ..., the Tcl interpreter attempts to substitute things like variables and commands as far as possible. This means that if (like in this case) you create a button and set its command with this invocation

button .top.btn -command [destroy .top]

Tcl executes the command destroy .top as part of executing your button invocation (and inserts the result value of the execution as a command string passed to the command option). You don't want that to happen (usually, and certainly not in this case, as it saws off the branch your GUI is sitting on), so you need to prevent Tcl from substituting this particular part of the invocation.

If you don't need to substitute anything in the command string that you pass to the command option, you can write it like this

button .top.btn -command {destroy .top}

or (a little more fragile)

button .top.btn -command \[destroy .top]

but in some cases you need to substitute some part of the command string without executing the command. This won't work:

set w .top
button $w.btn -command {destroy $w}

since that would have the button try to execute the unsubstituted command string destroy $w.

In such cases, it's usually sufficient to wrap the command string in list:

set w .top
button $w.btn -command [list destroy $w]

So, instead of

button .topbox.btn_1 \
    -text "Destroy" \
    -width 150 \
    -background green \
    -command [destroy .topbox]

you should write

button .topbox.btn_1 \
    -text "Destroy" \
    -width 150 \
    -background green \
    -command [list destroy .topbox]

or possibly give the command option as

    -command {destroy .topbox}

since you don't need to substitute anything.

Peter Lewerin
  • 13,140
  • 1
  • 24
  • 27
  • Thanks ! Your right, my only differnce was the type of brace, because I had something else in there before which actually needed substitution. – Lumpi Jan 24 '14 at 15:16
  • @Lumpi If you're thinking about anything more complicated than what you can do with a simple literal or what you can make easily with `list`, use a helper procedure. It's the easiest way by far. – Donal Fellows Jan 24 '14 at 19:52