2016-06-21 4 views
1

Ich arbeite an einer GUI mit tcl/tk 8.5.9 und Python 3.5.1 unter Mac OS X 10.11.5.Wie erhalten Sie mehrere tk.text-Widgets zur Anpassung an die Inhaltshöhe?

Ich versuche, eine Art Liste von tk.text Widgets zu erstellen, die eine feste Breite haben und Höhe anpassen, um ihren Inhalt anzupassen, wann immer es (vom Benutzer oder programmgesteuert) geändert wird. Dies sollte sowohl echte als auch verpackte Dispylines berücksichtigen.

Ich habe dies mit Antworten von Tkinter Resize text to contents und here zu arbeiten. Die Anpassung an Benutzereingaben funktioniert jedoch nur für das zuletzt erstellte Text-Widget. Alle zuvor erstellten Text-Widgets werden nicht mehr verkleinert, sobald ein neues hinzugefügt wurde.

Ich denke, das Problem könnte irgendwo in den Linien, die sich mit den Bindtags beschäftigen. Da ich neu bei tkinter, python und relativ neu im Programmieren bin, bin ich mir nicht sicher, ob ich bindtags richtig verstehe.

Jede Hilfe sehr geschätzt wird, hier ist mein 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() 
+0

ich Ihr Programm laufen und ich kann Ihr Problem nicht reproduzieren, weil unabhängig von der Länge des Textes I einzufügen ist, die Höhen sind wieder- automatisch angepasst, um den Text anzupassen und zu verpacken. –

+0

@BillalBEGUERADJ: Danke für Ihre Rückmeldung, das Problem betrifft nur die Größenanpassung, wenn der Benutzer einen Zeilenumbruch oder eine Zeile eingibt, die umbrochen wird. Und das zuletzt erstellte Text-Widget verhält sich so, wie ich es möchte. Außerdem: Ich bin auf dem Mac. Ich habe die Frage aktualisiert, um diese Punkte zu klären. – Sam

Antwort

1

Ich löste dies durch die bindtags Konfiguration und das Ereignisses Zurücksetzen auf Key-Ereignissen Bindung jedes Mals, wenn der Text-Widget auf den Fokus (Ereignisbindung bekommt Fokus).

Wahrscheinlich nicht eine saubere Lösung, aber es scheint gut zu funktionieren:

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