python tkinter textbox Wörter markieren?

2 Antworten

Eine Lösung könnte so aussehen:

#!/usr/bin/env python3

import re
import tkinter as tk

class HighlighterTextbox(tk.Text):
  def __init__(self, *master, word_to_highlight="", **options):
    tk.Text.__init__(self, *master, **options)

    self.clear_modified_flag()
    self.bind("<<Modified>>", self.has_been_modified)

    self.tag_configure("HIGHLIGHTED", foreground="blue")
    self.word_to_highlight = word_to_highlight

  def clear_modified_flag(self):
    self.reset_modified_currently = True

    try:
      self.tk.call(self._w, "edit", "modified", 0)
    finally:
      self.reset_modified_currently = False

  def has_been_modified(self, event=None):
    if self.reset_modified_currently:
      return

    self.clear_modified_flag()
    self.on_modified(event)

  def on_modified(self, event=None):
    text = self.get("1.0", "end-1c")
    matches = re.finditer(self.word_to_highlight, text)

    for match in matches:
      self.tag_add("HIGHLIGHTED", "1.0+" + str(match.start()) + "c", "1.0+" + str(match.end()) + "c")

class TextPad(tk.Frame):
  def __init__(self, parent, *args, **kwargs):
    tk.Frame.__init__(self, parent, *args, **kwargs)

    self.textfield = HighlighterTextbox(self, word_to_highlight="Hello")
    self.textfield.focus()
    self.textfield.pack(fill="both", expand=True)

if __name__ == "__main__":
  root = tk.Tk()
  TextPad(root).pack(expand=1, fill="both")
  root.mainloop()

Ich werde die Lösung nur grob beschreiben.

Zunächst wird eine eigene Textbox-Klasse angelegt, die von Tk.Text erbt. In dieser wird das Modified-Event an die Box (bzw. den Handler has_been_modified) gebunden, sodass auf jede Änderung reagiert werden kann. Allerdings setzt die Standardtextbox nach einer Änderung einen internen Flag (modified), der sich folgend nicht wieder selbst aktualisiert und somit verhindert, dass der gebundene Handler bei jeder Änderung aufgerufen werden kann. Daher wird der interne Flag nach jeder Modifikation manuell zurückgesetzt. Um zu verhindern, dass deswegen der eigene Handler mehrmals aufgerufen wird (das Zurücksetzen triggert ebenso das Modified-Event ein erneutes Mal), wird der reset_modified_currently-Flag als Blocker verwendet.

In on_modified wird die Logik formuliert, die den Text kennzeichnen soll. Dafür wird der Text geholt und alle Vorkommen des gesuchten Wortes werden ermittelt. Die Positionen dieser Vorkommen werden mit einem Tag ausgestattet, der die blaue Schriftfarbe definiert. Beim Löschen von Buchstaben werden die Wörter aber noch nicht aktualisiert. Das wäre etwas, was man sich als Nächstes anschauen könnte. Ebenso könnte man sicherlich verhindern, dass mit jeder Textänderung die Tags neu zur Textbox zugefügt werden.

Die Textbox wird zuguter Letzt in ein Fenster / Frame eingebettet.

Wenn du nun noch nach detaillierten Informationen zu einzelnen Funktionen suchst, kannst du diese aus der Dokumentation oder von Effbot beziehen. Anpassungen und Erweiterungen überlasse ich gänzlich dir.