如何获得多重tk.文本小部件调整到内容高度?

2024-10-02 20:41:10 发布

您现在位置:Python中文网/ 问答频道 /正文

在Mac.5.5和tcl操作系统上运行的tcl图形用户界面。在

我想建立一个tk.文本具有固定宽度和调整高度以适应其内容的小部件(由用户或以编程方式更改)。这应该考虑真实的以及包装的显示线。在

我使用来自Tkinter Resize text to contents和{a2}的答案来实现这一点。但是,调整到用户输入只适用于最后创建的文本小部件。所有先前创建的文本小部件都不会再调整大小,只要添加了一个新的。在

我想问题可能出在处理bindtags的行中。由于不熟悉tkinter、python,而且总体上对编程还比较陌生,我不确定自己是否正确理解bindtag。在

非常感谢任何帮助,以下是我的代码:

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()

Tags: totext文本selfsizeis部件update
1条回答
网友
1楼 · 发布于 2024-10-02 20:41:10

我通过配置bindtags并在每次文本小部件获得焦点(FocusIn上的事件绑定)时重置键事件上的事件绑定来解决这个问题。在

可能不是一个干净的解决方案,但似乎效果良好:

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)
        self.configure_bindtags(event=None)

        # solution: additional binding that resets the binding for <Key> events whenever the text widget gets the focus
        self.bind('<FocusIn>', self.configure_bindtags)

    def configure_bindtags(self, event):
        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)

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)

root.mainloop()

相关问题 更多 >