Массив, не видимый в процедуре пространства имен, но видимый без пространства имен в процедуре - PullRequest
0 голосов
/ 30 августа 2018

Утро всем,

В приведенном ниже коде показано пространство имен с процедурами, а также имеется массив с именем ds_out.

Если я запускаю этот код и нажимаю кнопку ввода, я получаю ошибку:

«Ошибка: невозможно прочитать» ds_out (0) !: нет такой переменной

Если я поставлю галочку и нажму Enter, появится сообщение:

«KL15 - это: 1», и если я сниму флажок, будет написано «KL15 - это: 0»

Если я закомментирую пространство имен и просто укажу процедуры, все будет работать нормально.

Может кто-нибудь сказать мне, почему, пожалуйста?

namespace eval RELAY_SELECT {
tk::labelframe .rs -text "Relay Selection"
array set ds_out {
0   0
1   0 
}
proc create_RS_Labels {} {
tk::label .rs.kl15_lb -text "KL15" -justify center -width 5
}
proc create_RS_CBoxes {} {
tk::checkbutton .rs.kl15_cb -width 1 -height 1 -variable kl15_cb -command {if {$kl15_cb} {
set ds_out(0) 1
set ds_out(1) 1
} else {
set ds_out(0) 0
set ds_out(1) 0
} }
}
proc create_RS_enter_Button {} {
tk::button .rs.enter -borderwidth 1 -height 1 -text "Enter" -width 5 -command {if {$kl15_cb} {
set ds_out(0) 1
set ds_out(1) 1
puts "KL15 is: $ds_out(0)"
} else {
puts "KL15 is: $ds_out(0)"
set ds_out(0) 0
set ds_out(1) 0
}
}
}
proc create_RS_LabelFrame {} {

place .rs -x 10 -y 10
grid .rs.kl15_lb -row 0 -column 0 
grid .rs.kl15_cb -row 0 -column 1   
grid .rs.enter -row 12 -column 0 -columnspan 6
}
create_RS_Labels
create_RS_CBoxes
create_RS_enter_Button
create_RS_LabelFrame
}

1 Ответ

0 голосов
/ 30 августа 2018

У вас проблемы с изменяемой областью видимости.

Обратные вызовы команды Tk всегда оцениваются в глобальной области видимости. Ваш массив не в глобальной области видимости (а другие переменные, такие как kl15_cb , являются глобальными, несмотря на то, что вы не ожидаете, что они будут). Это может очень запутать очень быстро; вам настоятельно рекомендуется сделать вспомогательные процедуры для всех обратных вызовов. Вот ваш код переработан в том, как это должно быть ради здравомыслия; обратите особое внимание на Note! комментарии там.

namespace eval RELAY_SELECT {
    # Note! Declare variables in namespaces, always, to avoid an obscure misfeature!
    variable kl15_cb 0
    variable ds_out
    array set ds_out {
        0   0
        1   0 
    }

    proc create_RS_Labels {frame} {
        tk::label $frame.kl15_lb -text "KL15" -justify center -width 5
    }

    proc create_RS_CBoxes {frame} {
        # Note! Fully qualified variable name!
        # Note! [namespace code] to make callback script!
        tk::checkbutton $frame.kl15_cb -width 1 -height 1 -variable ::RELAY_SELECT::kl15_cb \
                -command [namespace code { RS_CBox_callback }]
    }

    proc RS_CBox_callback {} {
        # Note! [variable] with *ONE* argument to bring var into procedure scope
        variable kl15_cb
        variable ds_out
        if {$kl15_cb} {
            set ds_out(0) 1
            set ds_out(1) 1
        } else {
            set ds_out(0) 0
            set ds_out(1) 0
        }
    }

    proc create_RS_enter_Button {frame} {
        tk::button $frame.enter -borderwidth 1 -height 1 -text "Enter" -width 5 \
                -command [namespace code { RS_enter_callback }]
    }

    proc RS_enter_callback {} {
        variable kl15_cb
        variable ds_out
        if {$kl15_cb} {
             set ds_out(0) 1
             set ds_out(1) 1
             puts "KL15 is: $ds_out(0)"
        } else {
             puts "KL15 is: $ds_out(0)"
             set ds_out(0) 0
             set ds_out(1) 0
        }
    }

    proc create_RS_LabelFrame {frame} {
        place $frame -x 10 -y 10
        grid $frame.kl15_lb -row 0 -column 0 
        grid $frame.kl15_cb -row 0 -column 1   
        grid $frame.enter -row 12 -column 0 -columnspan 6
    }

    tk::labelframe .rs -text "Relay Selection"
    create_RS_Labels .rs
    create_RS_CBoxes .rs
    create_RS_enter_Button .rs
    create_RS_LabelFrame .rs
}

Ради собственного здравого смысла я тоже все отступил условно.

...