使用Python3.3独立于平台解决此问题。
对于Entry
小部件,您可以将变量绑定到此小部件的文本内容,如下所示(请注意Entry
构造函数中的textvariable
参数):
var = tkinter.StringVar()
entryField = tkinter.Entry(master, textvariable=var)
e.pack()
var.set("a new value") # entryField text now updated with this value
s = var.get() # whatever text now appears in entryField
但是,对于Text
小部件,没有这样的变量绑定特性。类Text
如果感兴趣的话,它的定义应该在Windows版本中python 3.3的%python dir%/Lib/tkinter/\uu init.py的第2927行开始。
如何用Text
小部件最好地模拟这个变量绑定特性?我的想法是将一个tkinter.StringVar
绑定到一个Text
小部件,然后获取/设置所有文本。
最后,我继承了tkinter.Frame
作为Text
包装器,它接受了textvariable
构造函数参数,该参数预期为tkinter.Variable
实例。在下面的例子中,我没有继承Text
的唯一原因是我也想要一个滚动条,但这并不重要。
下面是我的实验代码。与我最初的问题以及问题是如何解决的完全相关(?),重要的行是self.textvariable.get = self.GetText
和self.textvariable.set = self.SetText
。基本上,我正在重写传入的tkinter.Variable
对象的get和set方法到我自己的设备。。。
class TextExtension( tkinter.Frame ):
"""Extends Frame. Intended as a container for a Text field. Better related data handling
and has Y scrollbar now."""
def __init__( self, master, textvariable = None, *args, **kwargs ):
self.textvariable = textvariable
if ( textvariable is not None ):
if not ( isinstance( textvariable, tkinter.Variable ) ):
raise TypeError( "tkinter.Variable type expected, {} given.".format( type( textvariable ) ) )
self.textvariable.get = self.GetText
self.textvariable.set = self.SetText
# build
self.YScrollbar = None
self.Text = None
super().__init__( master )
self.YScrollbar = tkinter.Scrollbar( self, orient = tkinter.VERTICAL )
self.Text = tkinter.Text( self, yscrollcommand = self.YScrollbar.set, *args, **kwargs )
self.YScrollbar.config( command = self.Text.yview )
self.YScrollbar.pack( side = tkinter.RIGHT, fill = tkinter.Y )
self.Text.pack( side = tkinter.LEFT, fill = tkinter.BOTH, expand = 1 )
def Clear( self ):
self.Text.delete( 1.0, tkinter.END )
def GetText( self ):
text = self.Text.get( 1.0, tkinter.END )
if ( text is not None ):
text = text.strip()
if ( text == "" ):
text = None
return text
def SetText( self, value ):
self.Clear()
if ( value is not None ):
self.Text.insert( tkinter.END, value.strip() )
旁注:很明显,我来自不同的语言,基于间隔。对不起,我没办法。
我想我回答了我自己的问题。这是否是重写传入函数的tkinter.Variable
对象的已知方法的正确方法,就像我刚才所做的那样,这是一个单独的问题,我将不得不询问/研究,即使这是一段私人代码,永远不会在我的应用程序外使用。我承认,这确实提出了一个问题,这是否是一个有效的解决办法。
如果您愿意以危险的方式生活,那么就有可能连接到文本小部件的内部,并让它在内容更改时调用函数,而不管它如何更改。
诀窍是用代理替换底层的tk小部件命令。这个代理负责执行真实文本小部件将要执行的任何操作,然后发送一个虚拟事件(如果它所做的是插入或删除文本)。
有了它,只需要设置一个绑定到该事件,并在变量上放置一个读取跟踪。当然,如果尝试在文本中插入小部件或图像,它们将不会反映在textvariable中。
这里有一个快速而肮脏的例子,没有在任何真实的测试中。这使用了与我在文本小部件中实现行号相同的技术(请参见https://stackoverflow.com/a/16375233)
不确定这是不是你想做的,但这对我有效:
每次在文本小部件中释放密钥时,它都将运行
do_something
我发现问题中提出的类并没有像典型的Tkinter小部件那样处理textvariable,所以我自己做了一些重写,使其成为一个“适当的”小部件。:-)
通常,textvariable实例不会被传递给它的类修改,而是在变量更改时调用它的get()函数(通过跟踪检测),而set()函数则通过某个内部钩子调用。这样,它可以被其他小部件使用。此外,猴子修补也许不是最安全的做法。
在本例中,使用文本小部件绑定方法和
<<Modified>>
标记。它不是一个典型的持续触发的“on_change”事件,而是在有人修改小部件的内容时触发的,它提供了一种机制来帮助发出值已被修改的信号。因此,每次触发后,需要使用Text.edit_modified(False)和var_modified函数重置它,以便再次触发。但它起作用了,我没有得到<<Change>>
为我工作。最后,为了避免不需要的循环,文本变量的跟踪在文本修改中被暂时禁用。此外,如果小部件用于显式删除父项的情况(如在模式窗口中),则应调用unhook()方法进行清理,以避免出现问题。如果没有,就可以无视。
给你:
您可以在这里的on_post_merge_sql-function中看到正在使用和使用unhook的代码。
干杯!
相关问题 更多 >
编程相关推荐