繁体   English   中英

Tkinter 根据内容调整文本大小

[英]Tkinter Resize text to contents

是否可以调整 Tkinter 文本小部件的大小以适应其内容?

即:如果我放 1 行文本它会缩小,但如果我放 5 行它会增长

我能想到的唯一方法是每次用户在 Text 小部件中输入文本时计算宽度和高度,然后将小部件的大小设置为该大小。 但这里的限制是只有等宽字体才能正常工作,但无论如何:

import Tkinter

class TkExample(Tkinter.Frame):
   def __init__(self, parent):
      Tkinter.Frame.__init__(self, parent)
      self.init_ui()

   def init_ui(self):
      self.pack()
      text_box = Tkinter.Text(self)
      text_box.pack()
      text_box.bind("<Key>", self.update_size)

   def update_size(self, event):
      widget_width = 0
      widget_height = float(event.widget.index(Tkinter.END))
      for line in event.widget.get("1.0", Tkinter.END).split("\n"):
         if len(line) > widget_width:
            widget_width = len(line)+1
      event.widget.config(width=widget_width, height=widget_height)

if __name__ == '__main__':
    root = Tkinter.Tk()
    TkExample(root)
    root.mainloop()

在谷歌搜索的顶部找到了这个线程,因此,也许需要它的人会找到它。 即使经过数小时的搜索,也无法找到答案。 所以这是我想出的 HACK。

我想要一个弹出窗口,它可以正确地围绕 Text 小部件中任何未知但预先确定的文本,而不是用户输入。 此外,Text 小部件需要在其文本内容周围正确地适应自身。

tkinter.Label效果很好,但它没有tkinter.Text.tag_configuretkinter.Text.tag_bind ,我需要用tkinter.Text.tag_bind的富文本标签替换一些 HTML 标签。 tkinter.Text有富文本标签,但不能很好地扩展,而tkinter.Label很好地扩展,但没有富文本标签。 此外,我只是讨厌滚动条和自动换行,除非他们真的需要。 这正是我想要的。 虽然,这只是本论坛的一个非常简单的工作摘要。 适用于任何字体。 仅在 Ubuntu 13.10 (Linux) 中使用 Python 3.3 进行测试。

#!/usr/bin/env python3

import tkinter as tk

class MyFrame(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self)

        root = self.master
        root.title("My Window Title")

        # Pack Frame into root window and make it expand in "both" x and y
        self.pack(side="top", fill="both", expand=True, padx=10, pady=10)
        # Statistical weight of 1 = 100% for cell (0, 0) to expand 100%
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)

        # The string text
        text = """Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed
diam nonummy nibh euismod tincidunt ut laoreet dolore magna
aliquam erat volutpat. Ut wisi enim ad minim veniam, quis
nostrud exerci tation ullamcorper suscipit lobortis nisl ut
aliquip ex ea commodo consequat. Duis autem vel eum iriure
dolor in hendrerit in vulputate velit esse molestie consequat,
vel illum dolore eu feugiat nulla facilisis at vero eros et
accumsan et iusto odio dignissim qui blandit praesent luptatum
zzril delenit augue duis dolore te feugait nulla facilisi. Nam
liber tempor cum soluta nobis eleifend option congue nihil
imperdiet doming id quod mazim placerat facer possim assum.
Typi non habent claritatem insitam; est usus legentis in iis qui
facit eorum claritatem. Investigationes demonstraverunt lectores
legere me lius quod ii legunt saepius. Claritas est etiam
processus dynamicus, qui sequitur mutationem consuetudium
lectorum. Mirum est notare quam littera gothica, quam nunc
putamus parum claram, anteposuerit litterarum formas
humanitatis per seacula quarta decima et quinta decima. Eodem
modo typi, qui nunc nobis videntur parum clari, fiant sollemnes
in futurum."""

        # Add a tk.Text widget to Frame (self) and its configuration
        textwidget = tk.Text(self, wrap="none", font=("Comic Sans MS", 12),
                             padx=10, pady=10)
        textwidget.grid(row=0, column=0, sticky="nesw")
        # Add the text to textwidget and disable editing
        textwidget.insert(tk.END, text)
        textwidget.config(state=tk.DISABLED)

        # Here is where the HACK begins
        def is_scroll(wh, lower, upper):
            nonlocal size
            size[wh][0] = upper < '1.0' or lower > '0.0'
            size[wh][1] += 20 * size[wh][0] # += 1 for accuracy but slower
        # Call the is_scroll function when textwidget scrolls
        textwidget.config(xscrollcommand=lambda *args: is_scroll('w', *args),
                          yscrollcommand=lambda *args: is_scroll('h', *args))

        # Add a tk.Button to the Frame (self) and its configuration
        tk.Button(self, text="OK", command=self.quit).grid(row=1, column=0,
                                                           sticky="we")

        # For reasons of magic, hide root window NOW before updating
        root.withdraw()

        # Initially, make root window a minimum of 50 x 50 just for kicks
        root.geometry('50x50')
        size = {'w': [False, 50], 'h': [False, 50]}
        # Update to trigger the is_scroll function
        root.update()
        while size['w'][0] or size['h'][0]:
            # If here, we need to update the size of the root window
            root.geometry('{}x{}'.format(size['w'][1], size['h'][1]))
            root.update()

        # Center root window on mouse pointer
        x, y = root.winfo_pointerxy()
        root.geometry('+{}+{}'.format(x-size['w'][1]//2, y-size['h'][1]//2))

        # Now reveal the root window in all its glory
        root.deiconify()

        # Print textwidget dimensions to the console
        print(textwidget.winfo_width(), textwidget.winfo_height())

def main():
    """Show main window."""
    MyFrame().mainloop()

if __name__ == '__main__':
    main()

说明: TRICK 甚至不用担心尝试直接扩展或缩小 Text 小部件的徒劳。 答案有点违反直觉,因为一个人的第一个想法是直接使用该 Text 小部件并对其进行处理。 相反,展开根(最外层)窗口(在本例中为self.master ),并且只留下 Text 小部件。 十分简单。

将 Text 小部件粘贴( "nesw" )到 Frame 中,该小部件在根窗口中进行 100% 扩展。 随着根窗口的扩展,其中的 Frame 和 Text 小部件也会扩展。 但是,当您扩展根窗口时,如果 Text 小部件的xscrollcommandyscrollcommand (不再滚动)的lowerupper已经消失,则 TEST 。 这些命令将lowerupper参数作为百分位数发送到滚动条所需的回调函数,通常是tkinter.Scrollbar.set 但是,我们使用这些命令是因为我们根本不需要滚动条或任何滚动。 我们想要一个完美的合身。

如果lowerupper消失(下限 <= 0.0 和上限 >= 1.0),这意味着我们的 Text 小部件周围有一个完美契合的窗口,该窗口也完美契合其文本内容。 多田!

添加了一个按钮来证明即使添加了其他小部件它仍然可以正常工作。 删除一些文本以查看它仍然完美合身。

编辑:短方法:

text.pack(side="top", fill="both", expand=True, padx=0, pady=0)

通过重新使用 sc0tt 的答案和此处 Bryan Oakley 的答案获取 Text tkinter 小部件的行数,我们可以获得这个现成的代码(发布在这里以供将来参考)也适用于比例字体

import Tkinter as Tk
import tkFont

class Texte(Tk.Text):
    def __init__(self, event=None, x=None, y=None, size=None, txt=None, *args, **kwargs):
        Tk.Text.__init__(self, master=root, *args, **kwargs)
        self.font = tkFont.Font(family="Helvetica Neue LT Com 55 Roman",size=35)
        self.place(x=10,y=10)
        self.insert(Tk.INSERT,' blah ')
        self.config(font=self.font)
        self.update_size(event=None)
        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):
        width=0
        lines=0
        for line in self.get("1.0", "end-1c").split("\n"):
            width=max(width,self.font.measure(line))
            lines += 1
        self.config(height=lines)
        self.place(width=width+10)

root = Tk.Tk()
root.geometry("500x500")
Texte()
root.mainloop()

以 sc0tt 的帖子为基础,如果您不使用换行符(例如,仅使用固定宽度并使高度成为唯一的扩展变量),则该辅助函数可以很好地工作:

def update_height(event):
    text_height = (str(event.widget.index('1.end')) )
    text_int = int(re.search(".(\d+)", text_height).group(1))
    widget_height = int(int(text_int)/160) + 1
    event.widget.config(height=widget_height)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM