I have a Tkinter use case where I need a text box that is multi-line and can filter and replace characters.
Here is a simplified but applicable use case:
A multi-line text control
Filters so only characters "A", "B", "C", "0", "1" and "*" can be typed
An exception to the filter above is that lower case characters can be typed, but they will converted to uppercase
Because I need a multi-line control, the Entry widget is out (it is single-line only). This means I need to use the Text widget.
With the Text widget, I can filter on text using the bind method. Example:
self.my_text_field.bind('<KeyPress>',self.filter_text)
def filter_text(self, event):
character_set = ["A", "B", "C", "0", "1", "*"]
if event.char.upper() in character_set:
#Do nothing. Accept character.
pass
else:
#Ignore character.
return 'break'
The above code works fine for filtering, but it does not achieve the character replacement to replace any lower characters with their .upper() version.
So, if I want to actually do character replacement, I can use the validatecommand to achieve the same filtering as I get with the .bind method above, and if I want to actually replace characters, I need to use the invalidcommand to replace text when my validate function returns false. See this thread which covers the validatecommand and invalidcommand:
Interactively validating Entry widget content in tkinter
The problem is that validatecommand and invalid are only available on the Entry widget (which again is single line and won't work in my use case).
I experimented with using .bind on KeyRelease and using .get and .insert to replace the text of the Text widget, but that is messy and seems impractical because changing the control's text with .delete and .insert results in programmatic versions and additional instances of KeyPress/KeyRelease.
I can always ignore lower case characters with my filter and still use the Text control with what I have found to date, but I really would like to convert the characters to uppercase as well.
I've looked a good bit on StackOverflow and other resources and haven't found a solution. Any help would be appreciated.