2016-10-06 2 views
1

Может ли кто-нибудь помочь мне в этой ситуации? Я пытаюсь создать графический интерфейс, который используется для демонстрации цвета всей матрицы RGB на холсте. К сожалению, GUI не отвечает, и он не меняет цвета, как ожидалось, до тех пор, пока цикл не будет завершен. Что-то не так? Я часто сталкиваюсь с этой проблемой, если я настраиваю виджет в цикле.Tk GUI не отвечает

package require Tk 
package require math 
proc changeColor {rM gM bM} { 
    for {set r 0} {$r<=$rM} {incr r} { 
     for {set g 0} {$g<=$gM} {incr g} { 
      for {set b 0} {$b<=$bM} {incr b} { 
       set rHex [format %02X $r] 
       set gHex [format %02X $g] 
       set bHex [format %02X $b] 
       set mark # 
       set color [append mark $rHex $gHex $bHex] 
       .cv config -bg $color 
       .lb config -text "[format %03d $r] [format %03d $g] [format %03d $b]" 
       after 500 
      } 
     } 
    } 
} 

canvas .cv 
ttk::label .lb 
ttk::button .bt -text Run -command {changeColor 255 255 255} 

grid .cv -row 0 -column 0 -sticky news 
grid .lb -row 1 -column 0 -sticky we 
grid .bt -row 2 -column 0 

Code_Snapshot

GUI_Snapshot

+0

Попробуйте использовать * update idletasks * перед строкой * после *. –

+0

Привет Марио, очень ценю вашу любезную помощь. Оно работает. – Samuel

ответ

2

Тк (и Tcl) не обрабатывает никаких событий на всех во время синхронного after 500. Он только останавливает процесс для этого 500 мс.

Для этого вам необходимо обработать события за это время. Заменить after 500 с:

after 500 {set go_on yes} 
vwait go_on 

Имейте в виду, что go_on есть глобальный, и что это может привести к проблемам с кодовым реентерабельности. Вы хотите отключить кнопку, выполняющую процедуру во время работы вашего кода.

Или вы можете использовать Tcl 8.6 и конвертировать все, чтобы быть сопрограммой. Затем вы сможете выполнять асинхронный сон без опасности заполнения стека:

proc changeColor {rM gM bM} { 
    for {set r 0} {$r<=$rM} {incr r} { 
     for {set g 0} {$g<=$gM} {incr g} { 
      for {set b 0} {$b<=$bM} {incr b} { 
       set rHex [format %02X $r] 
       set gHex [format %02X $g] 
       set bHex [format %02X $b] 
       set mark # 
       set color [append mark $rHex $gHex $bHex] 
       .cv config -bg $color 
       .lb config -text "[format %03d $r] [format %03d $g] [format %03d $b]" 
       ####### Notice these two lines... ######## 
       after 500 [info coroutine] 
       yield 
      } 
     } 
    } 
} 

##### Also this one needs to be altered ##### 
ttk::button .bt -text Run -command {coroutine dochange changeColor 255 255 255} 

# Nothing else needs to be altered 
+0

'update idletasks' будет работать, но он будет иметь проблемы, если вы сделаете что-то, что создает внешнее событие, например, перемещение или изменение размера окна ... –

+0

Привет, Дональд, большое вам спасибо за подробные инструкции. – Samuel

Смежные вопросы