我想要做的是修改或创建一个在主线程中从不同线程创建的小部件,我读到tk不是安全线程,我无法完成此任务。我只想在尝试这样做时用尽我的选择。当我尝试创建一个小部件时,例如:
set threadID [thread::create {
label .test -text "hello"
thread::wait
}]
我也试试这个:
label .test -text ""
set threadID [thread::create]
thread::send $threadID [list .test configure -text "HEllo World"]
这给我一个错误,说命令标签无效,那么有没有办法从不同的线程创建/修改一个小部件?
答案 0 :(得分:2)
这是不可能的。如果您需要从不同的线程访问/修改小部件,我建议采用以下方法:
thread::send
将读/写命令发送到GUI线程(可能处于阻塞模式)。您必须自行决定何时必须使用-async
标志。
线程安全工具包很少见(如果可能的话),例如Java的Swing不是线程安全的。通常的方法是将消息发布到AWT-Thread中处理的事件队列(例如,使用SwingUtilities.invokeLater
),就像这里一样。
答案 1 :(得分:1)
每个小部件都与单个解释器紧密相关,并且每个解释器都与单个线程紧密相关;你想要什么都行不通。
最简单的解决方法是将命令放在委托给GUI线程的其他线程中,以修改小部件:
pack [label .l]
thread::send $threadID "
proc .l args {
thread::send [thread::current] \[list .l {*}\$args\]
}
"
之后,其他线程可以使用:
.l configure -text "Hello, World!"
它会起作用。好吧,主要是。 (-textvariable
选项不会跨越线程而没有相当多的带有跟踪的魔法,并且图像也是解释器绑定的。)您也将无法在没有更多的情况下调整窗口小部件的几何管理工作,但这不是一个常见的问题。
另一种方法是在-use
的框架中嵌入带有-container
的顶层,但这不是我获得最大成功的选项。不过,它应该跨进程工作(好吧,无论如何在Unix / X11上),所以它也可以用于线程。