簡體   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