将Python变量传递给`Tkinter.Tcl().eval()`
我可以加载一个Tcl脚本,并像这样运行其中的一个proc
:
import Tkinter
>>> tclsh = Tkinter.Tcl()
>>> tclsh.eval('source {myscript.tcl}')
>>> tclsh.eval('myproc')
...[output of proc]
>>>
但是,如果我想给这个proc
传递一些变量,我必须这样做(假设这个proc
需要一个dict
作为参数):
>>> tclsh.eval('dict set spec num 10000')
>>> tclsh.eval('dict set spec time 10000')
>>> tclsh.eval('dict set spec rate 10')
有没有更简单、更符合Python风格的方法来在Tkinter中做到这一点?我见过变量类,但它们似乎没有字典风格的变量,甚至没有和Tcl解释器的部分连接起来。
1 个回答
5
变量类的想法很好,但目前没有专门的字典版本,这有点不太方便。不过,你可以简单地使用字符串版本(这样会影响性能,但这个问题是可以解决的)。
先说简单的方法。Tcl 的字典有一个字符串表示形式,并且可以自动从字符串转换为字典,反之亦然。所以如果你有一个需要字典的过程,你可以直接传入字典的字符串表示,它就能正常工作。
interp = tkinter.Tcl()
myvar = tkinter.StringVar()
def pydict2tcldict(d):
return tkinter._stringify(list(d.items()))
d = {'num': 10000, 'time': 10000, 'rate': 10}
myvar.set(pydict2tcldict(d))
interp.eval("""source {myscript.tcl}
myproc $%s""" % myvar._name)
当然,你可以通过提供一个特殊的字典变量包装器来让事情变得更好更快,而不是通过字符串表示进行慢速转换,具体可以参考变量类的实现。
但从根本上说,tkinter 只是缺少了一些在 _tkinter.c 模块中的转换函数(可以看看 AsObj
/FromObj
/CallArgs
),如果添加适当的映射代码(这很简单),你就可以直接这样做,事情就解决了(而且速度也会相当快):
interp.call("myproc", d)
对 modules/_tkinter.c
的修改应该是相当简单的,阅读 Tcl 字典 C API 的手册和 Python 映射 C-API 后,你会发现这很容易实现(可以参考 https://www.tcl.tk/man/tcl8.6/TclLib/DictObj.htm 和 https://docs.python.org/2/c-api/mapping.html)。