2016-06-21 24 views
1

我正在用的Tcl/Tk 8.5.9和3.5.1的Python在Mac OS X 10.11.5的GUI。如何讓多個tk.text窗口小部件適應內容高度?

我試圖創造一種具有固定寬度,只要它(由用戶或編程)改變調整高度,以適應其內容tk.text部件的清單。這應該考慮到實際以及包裹displaylines。

我得到這個答案,使用從Tkinter Resize text to contentshere工作。但是,調整到用戶輸入僅適用於最後創建的文本窗口小部件。所有以前創建的文本小部件不會再調整大小,一旦添加新小部件。

我認爲這個問題可能會在與bindtags處理線的某處。作爲tkinter,python的新手而且對編程來說相對較新,我不確定我是否正確理解綁定標籤。

任何幫助是非常讚賞,這裏是我的代碼:

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

我運行您的程序,我無法重現你的問題,因爲無論我插入的是文本的長度,高度重自動調整大小以適應和包裹文本。 –

+0

@BillalBEGUERADJ:感謝您的反饋,問題只涉及當用戶輸入一個換行符,或者被纏繞的線路調整。最後創建的文本小部件的行爲就像我想要的那樣。另外:我在Mac上。我更新了這個問題以澄清這些問題。 – Sam

回答

1

我解決了這個通過配置bindtags和重置事件的每個文本組件獲得焦點(事件綁定的時間,在關鍵事件結合專注於)。

可能不是一個乾淨的解決方案,但它似乎很好地工作:

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() 
相關問題