Seite 1 von 1
Eingaben filtern bei Tkinter.Text() ?!?
Verfasst: Freitag 15. August 2014, 23:25
von jens
Ich würde gern alle Eingaben vom Benutzer in einer Tkinter.Text() abfangen und evtl. ändern. Wie?
Ich könnte das machen (pseudocode):
Code: Alles auswählen
self.text = Tkinter.Text(self.root, height=30, width=80)
self.text.config(
state=Tkinter.DISABLED # make textbox "read-only"
)
self.root.bind("<Key>", self.event_key_pressed)
def event_key_pressed(self, event):
char = event.char
self.text.config(state=Tkinter.NORMAL)
char = foobar(char)
self.text.insert("end", char)
self.text.see("end")
self.text.config(state=Tkinter.DISABLED)
Das funktioniert theoretisch... Aber kann kann man nicht wirklich den Text editieren. Also z.B. mit den Cursortasten umherwandern usw.
Re: Eingaben filtern bei Tkinter.Text() ?!?
Verfasst: Sonntag 17. August 2014, 11:50
von bfm
Hallo,
da müsstest bei jedem Event den Keycode prüfen und wenn bestimmte Keycodes (Cursortasten) auftreten entsprechend reagieren.
hier mal aus meiner Sammlung einen Link. Der dürfte dir weiterhelfen:
http://docs.huihoo.com/tkinter/tkinter- ... names.html
mfg
Re: Eingaben filtern bei Tkinter.Text() ?!?
Verfasst: Sonntag 17. August 2014, 14:10
von jens
Ja, das mit den Cursortasten ist dann das eigentliche Problem, wenn ich "<Key>" abfange. Aber kann ich nicht den Event abfangen, ändern und dann wieder "weiterleiten" ?
Ich nutzte nun "ScrolledText" um den es geht.
Re: Eingaben filtern bei Tkinter.Text() ?!?
Verfasst: Sonntag 17. August 2014, 14:29
von BlackJack
Lesestoff:
http://effbot.org/tkinterbook/tkinter-e ... ndings.htm
`event_generate()` und 'break' als Rückgabewert sollten hier interessant sein.
Re: Eingaben filtern bei Tkinter.Text() ?!?
Verfasst: Sonntag 17. August 2014, 15:21
von jens
Also so geht es fast, aber nicht ganz (pseudocode):
Code: Alles auswählen
self.text = Tkinter.Text(self.root, height=30, width=80)
self.root.bind("<Key>", self.event_key_pressed)
def event_key_pressed(self, event):
keycode = event.keycode
char = event.char
log.critical("keycode %s - char %s", keycode, repr(char))
if not char or char not in string.letters:
log.critical("ignore")
return
converted_char = invert_shift(char)
log.critical("Convet char %r to %r", char, converted_char)
self.text.insert(Tkinter.CURRENT, converted_char)
return "break"
1. Die Zeichen werden nun doppelt eingegeben: Ich dachte "break" würde das bewirken.
2. Neue Zeichen landen nicht an der richtigen Stelle: Ich dachte Tkinter.CURRENT ist die aktuelle Cursor Position??!
Re: Eingaben filtern bei Tkinter.Text() ?!?
Verfasst: Dienstag 19. August 2014, 19:41
von jens
Also ich werde da nicht so ganz schlau draus...
Es gibt ja nicht nur "<Key>" sondern auch "<KeyPress>" und "<KeyRelease>"...
Hab mal alle drei per bind() genutzt und jeweils ein "break" zurück "gesendet".
Wenn man "<KeyPress>" oder "<KeyRelease>" nutzt, dann wird anscheinend "<Key>" wirkungslos. (Liegt vielleicht am return "break" ?!?)
Aber egal welches ich nutzte, das Zeichen landet zuerst schon im Text() bzw. ScrolledText() und erst danach, kommen die bind() Methoden zum Zuge. Also zu spät?
Also wie geht es?
Re: Eingaben filtern bei Tkinter.Text() ?!?
Verfasst: Mittwoch 20. August 2014, 20:35
von Schorlem
Hm, ich persönlich würde es nicht als beste Möglichkeit ansehen, alle Aktionen nochmal zu emulieren, was natürlich auch drauf ankommt, welche Features letztendlich implementiert werden sollen (Markieren, Cursor setzen, mit Tastatur markieren, ausschneiden, kopieren, einfügen, etc.). Was mich gerade noch quält ist, dass das Entry-Widget die perfekte Methode dafür bieten würde: Validation (mehr dazu
hier). Man könnte sich dann reichlich unelegant etwas daraus zusammenbasteln, allerdings ist direkt das nächste Problem da: Wie sollen Eingaben über mehrere Zeilen gelöst werden? Und was ist, wenn eine vorherige Zeile bearbeitet werden soll?
Leider und warum auch immer bietet 'Text' bzw. 'ScrolledText' keine dieser Validierungsfunktionen.
Außer dem wirklichen Emulieren der ganzen Tasten(kombinationen) erscheint mir momentan keine der genannten Lösungen greifbar :/
Naja, vielleicht hat noch jemand 'ne Idee^^
Re: Eingaben filtern bei Tkinter.Text() ?!?
Verfasst: Mittwoch 20. August 2014, 22:29
von jens
Danke für die Hinweise...
Eigentlich möchte ich nur Groß-/Kleinschreibung ändern, damit:
Code: Alles auswählen
def invert_shift(chars):
"""
>>> invert_shift("a")
'A'
>>> invert_shift("A")
'a'
>>> invert_shift("123 foo 456 BAR #!")
'123 FOO 456 bar #!'
"""
result = ""
for char in chars:
if char in string.ascii_lowercase:
# log.critical("auto shift lowercase char %s to UPPERCASE", repr(char))
char = char.upper()
elif char in string.ascii_uppercase:
# log.critical("auto shift UPPERCASE char %s to lowercase", repr(char))
char = char.lower()
result += char
return result
Re: Eingaben filtern bei Tkinter.Text() ?!?
Verfasst: Mittwoch 27. August 2014, 17:12
von jens
Hab nun eine Lösung:
https://gist.github.com/jedie/ae4f974d00a417183b2c
Das wichtigste:
Code: Alles auswählen
...
self.root.bind("<Key>", self.event_key)
...
converted_char = char.upper()
self.text.delete("insert-1c") # Delete last input char
self.text.insert(Tkinter.INSERT, converted_char) # Insert converted char
return "break"
Und im Einsatz:
https://github.com/jedie/DragonPy/commi ... ee2f0095be
Re: Eingaben filtern bei Tkinter.Text() ?!?
Verfasst: Donnerstag 28. August 2014, 11:05
von jens
Noch eine saubere Lösung gefunden:
https://gist.github.com/jedie/ae4f974d0 ... /revisions
Das Problem war, das ich
self.root.bind("<Key>"... gemacht habe und in dem Fall passender ist:
self.text.bind("<Key>"...
Dann bewirkt auch das
return "break" das kein Zeichen ankommt. Also muß ich auch nicht umständlich die alte Eingabe löschen.