Using Python 3.3 platform independent for this question.
For the Entry
widget, you can bind a variable to this widget's text contents like so (note the textvariable
parameter in Entry
constructor):
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
For the Text
widget however, there is no such variable binding feature. Class Text
definition should likely begin at line 2927 in %python dir%/Lib/tkinter/__init__.py for Python 3.3 in Windows releases if interested.
How can I best emulate this variable binding feature with the Text
widget? My idea is to bind a tkinter.StringVar
to a Text
widget and just get/set all text.
Update:
I ended up inheriting tkinter.Frame
as a Text
wrapper which takes in a textvariable
constructor parameter expected as a tkinter.Variable
instance. The only reason in my example below why I didn't inherit from Text
is just because I wanted a scrollbar too, but that's not important.
The following is my experimental code. For exact relevance to my original question and how the problem was resolved (?), the important lines are self.textvariable.get = self.GetText
and self.textvariable.set = self.SetText
. Basically, I'm overriding the passed-in tkinter.Variable
object's get and set methods to my own devices...
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() )
Side note: It's probably pretty obvious I'm coming from a different language based on spacing. I'm sorry, I can't help it.
I think I answered my own question. Whether or not this is the right thing to do to override the known methods of tkinter.Variable
objects passed into my functions like I just did is a separate question I'll have to ask/research even though this is a private bit of code that will never be used outside my app. And I acknowledge that this does beg the question whether this is an effective solution at all.