I'm working on a gui with tcl/tk 8.5.9 and python 3.5.1 on Mac OS X 10.11.5.
I'm trying to create a sort of list of tk.text widgets that have a fixed width and adjust height to fit their content whenever it is changed (by the user or programmatically). This should take into account real as well as wrapped displaylines.
I got this to work using answers from Tkinter Resize text to contents and here. However, adjusting to user input only works for the text widget that was created last. All previously created text widgets do not resize anymore, once a new one is added.
I think the problem might be somewhere in the lines that deal with the bindtags. Being new to tkinter, python and relatively new to programming in general, i'm not sure i understand bindtags properly.
Any help is much appreciated, here is my code:
from tkinter import *
class ResizingText(Text):
def __init__(self, parent, *args, **kwargs):
Text.__init__(self, master=parent, wrap='word', *args, **kwargs)
# event binding on resize because text.count method for displaylines returns a wrong number when widget is instantiated
self.bind('<Configure>', self.update_size)
bindtags = list(self.bindtags())
bindtags.insert(2, "custom")
self.bindtags(tuple(bindtags))
self.bind_class("custom", "<Key>", self.update_size)
def update_size(self, event):
if self.winfo_width() > 1:
self.unbind('<Configure>')
displaylines = self.count("1.0", "end", "displaylines")
self.config(height=displaylines)
root = Tk()
dynamic_text_1 = ResizingText(root, width=60)
dynamic_text_1.insert('1.0', "Longer text that is long enough to be wrapped into multiple display lines")
dynamic_text_1.grid(column=0, row=0)
# this text widget does not behave as expected:
# no resizing after user inputs a line break or a line long enough to be wrapped
dynamic_text_2 = ResizingText(root, width=60)
dynamic_text_2.insert('1.0', "Longer text that is long enough to be wrapped into multiple display lines")
dynamic_text_2.grid(column=0, row=1)
# this text widget behaves as expected
root.mainloop()