window name "" already exists in parent
потому, что список, питающий ds_out_i
, длиннее (вдвое длиннее!), Чем списки, питающие все остальные переменные; foreach
продолжается до тех пор, пока не пройдет все элементы для каждого элемента, присваивая переменные, списки которых были исчерпаны, пустой строкой.
Я предполагаю, что вы хотите либо использовать итерацию списка с двумя переменными для списка, в данный момент кормящего ds_out_i
, либо, что более вероятно, итерировать по списку пар. (Обратите внимание, что это немного нарушает ваш код в вашем обратном вызове; я скоро к этому вернусь.)
…
ds_out_i {{0 0} {2 0} {4 0} {6 0} {8 0} {10 0} {12 0} {14 0} {16 0} {18 0} {20 0} \
{22 0} {24 0} {26 0} {28 0} {30 0} {32 0} {34 0} {36 0} {38 0}} \
…
Другая ваша ошибка в том, что вы в настоящее время используете сложный встроенный скрипт для опции -command
(до checkbutton
). Не делай этого! С ним действительно тяжело работать. очень настоятельно рекомендуемый подход состоит в том, чтобы создать небольшую вспомогательную процедуру, а затем сделать опцию -command
простым сценарием, вызывающим эту процедуру и генерируемым с помощью команды list
.
Не использовать сложные скрипты непосредственно в обратных вызовах
Мы имеем в виду это. Если бы я мог сделать это мигающий баннер, я бы сделал. Это очень трудно понять правильно, и так легко ошибиться. Использование вспомогательных процедур намного легче получить право. Вот как это может выглядеть для вас.
proc rs_checkbutton_callback {varname index} {
# "parse" the arguments
global ds_out; # We're working with a global variable here
upvar "#0" $varname rs_cb; # Alias the named global variable as rs_cb
lassign $index a b; # This splits the two-part ds_out_i into two variables, a and b
if {$rs_cb} {
set ds_out($a) 1
set ds_out($b) 1
} else {
set ds_out($a) 0
set ds_out($b) 0
}
}
…
checkbutton .rs.$rs_cb -variable $rs_cb \
-command [list rs_checkbutton_callback $rs_cb $ds_out_i]
Я не уверен, что эта процедура обратного вызова делает то, что вы действительно хотите. Вместо этого было бы лучше сделать так:
proc rs_checkbutton_callback {varname index} {
# "parse" the arguments
global ds_out; # We're working with a global variable here
upvar "#0" $varname rs_cb; # Alias the named global variable as rs_cb
lassign $index a b; # This splits the two-part ds_out_i into two variables, a and b
if {$rs_cb} {
set ds_out([list $a $b]) 1
set ds_out([list $a [expr {$b + 1}]) 1
} else {
set ds_out([list $a $b]) 0
set ds_out([list $a [expr {$b + 1}]) 0
}
}