cup
cup

Reputation: 8267

Radio buttons behaving as one

I am building a dialog from a database and using the key as the variable for the radio buttons. Whenever I click on a radio button, all the buttons in the same column change. There are top level variables with the names in the dictionary

#!/usr/bin/tclsh
package require Tk
variable dict_config
set dict_config [dict create]
dict set dict_config config_single_step { 0 "Single step" "Single step"  "Run" }
dict set dict_config config_load    { 0 "Load"    "No load on startup"  "Load oad on startup" }
dict set dict_config config_news   { 0 "News"   "No news" "News Feed" }

# Callback to set the value
proc SetValue { ix val } {
    puts "Setting $ix to $val"
    variable dict_config
    set list_item [dict get $dict_config $ix]
    dict set dict_config $ix [lreplace $list_item 0 0 $val]
}

proc todo {} {
    puts "Coming soon to a screen near you"
}

proc DisplayOptions { dict_config } {
    set row 0
    dict for { ix list_item } $dict_config {
        # Extract data from the list
        set lab [lindex $list_item 1]
        set zero [lindex $list_item 2]
        set one [lindex $list_item 3]
        incr row

        # set dummy variable so the radio buttons respond correctly.
        set $ix [lindex $list_item 0]
        upvar 0 $ix debvar

        # Create widgets
        label .lab_$row -text $lab
        radiobutton .zero_$row -text $zero -variable debvar -value 0 -command "SetValue $ix 0"
        radiobutton .one_$row -text $one -variable debvar -value 1 -command "SetValue $ix 1"
        if { $debvar == 0 } {
            .zero_$row select
        } else {
            .one_$row select
        }

        # Layout widgets
        grid .lab_$row -sticky e -row $row -column 0
        grid .zero_$row -sticky w -row $row -column 1
        grid .one_$row -sticky w -row $row -column 2
    }

    incr row
    grid [button .butSave -text "Save" -command "todo"] -row $row -column 0    
}

# Let the user change them
DisplayOptions $dict_config

I have also tried $debvar - same thing happens. I can get it to work if I change the loop body to

        # Extract data from the list
        set lab [lindex $list_item 1]
        set zero [lindex $list_item 2]
        set one [lindex $list_item 3]
        incr row

        # set dummy variable so the radio buttons respond correctly.
        set r_$row [lindex $list_item 0]

        # Create widgets
        label .lab_$row -text $lab
        radiobutton .zero_$row -text $zero -variable r_$row -value 0 -command "SetValue $ix 0"
        radiobutton .one_$row -text $one -variable r_$row -value 1 -command "SetValue $ix 1"
        if { r_$row == 0 } {
            .zero_$row select
        } else {
            .one_$row select
        }

        # Layout widgets
        grid .lab_$row -sticky e -row $row -column 0
        grid .zero_$row -sticky w -row $row -column 1
        grid .one_$row -sticky w -row $row -column 2

I'm just wondering why r_$row works i.e. the buttons do not change as one but $debvar, which is an upvar alias does not.

Upvotes: 1

Views: 120

Answers (2)

L. Alejandro M.
L. Alejandro M.

Reputation: 629

The problem is in the "shared" variable debvar. You forgot apply the same approach for each row, on this way, you can do for example ...

        # set dummy variable so the radio buttons respond correctly.
        set $ix [lindex $list_item 0]
        upvar 0 $ix debvar_$row;# <-- Here add the row number

        # Create widgets
        label .lab_$row -text $lab
        ;#<-- Below these two lines are changed too 
        radiobutton .zero_$row -text $zero -variable debvar_$row -value 0 -command "SetValue $ix 0"
        radiobutton .one_$row -text $one -variable debvar_$row -value 1 -command "SetValue $ix 1"
        ;#<-- Finally you must use a way of dereferencing in order to use each debvar
        if { [set debvar_$row] == 0 } {
            .zero_$row select
        } else {
            .one_$row select
        }

I hope this help you,

Saludos!

Upvotes: 1

Schelte Bron
Schelte Bron

Reputation: 4813

The -variable option of widgets refers to a global variable. So that's in a different scope than the debvar in your DisplayOptions proc. They happen to have the same name, but otherwise have no relation at all.

By using the same global variable for all radiobuttons, they all work as one group. To have several groups of radiobuttons, you have to use a different global variable for each group, as you did with the r_$row version. Note that once again the r_$row local variable in your proc has no relation to the r_$row variable you use for the widgets.

You would actually be better off using a different (simpler) local variable, because if { r_$row == 0 } will always be false and it's overly complicated to get the value of a variable whose name is constructed as r_$row.

Upvotes: 1

Related Questions