简体   繁体   中英

How to change the color of certain words in the tkinter text widget?

I have a program that I want to be like the Python shell and change color of certain words when they are typed. Any help?

The main idea is to apply tags to the parts of text you want to customise. You can create your tags using the method tag_configure , with a specific style, and then you just need to apply this tag to the part of text you want to change using the method tag_add . You can also remove the tags using the method tag_remove .

The following is an example that uses tag_configure , tag_add and tag_remove methods.

#!/usr/bin/env python3

import tkinter as tk
from tkinter.font import Font

class Pad(tk.Frame):

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

        self.toolbar = tk.Frame(self, bg="#eee")
        self.toolbar.pack(side="top", fill="x")

        self.bold_btn = tk.Button(self.toolbar, text="Bold", command=self.make_bold)
        self.bold_btn.pack(side="left")

        self.clear_btn = tk.Button(self.toolbar, text="Clear", command=self.clear)
        self.clear_btn.pack(side="left")

        # Creates a bold font
        self.bold_font = Font(family="Helvetica", size=14, weight="bold")

        self.text = tk.Text(self)
        self.text.insert("end", "Select part of text and then click 'Bold'...")
        self.text.focus()
        self.text.pack(fill="both", expand=True)

        # configuring a tag called BOLD
        self.text.tag_configure("BOLD", font=self.bold_font)

    def make_bold(self):
        # tk.TclError exception is raised if not text is selected
        try:
            self.text.tag_add("BOLD", "sel.first", "sel.last")        
        except tk.TclError:
            pass

    def clear(self):
        self.text.tag_remove("BOLD",  "1.0", 'end')


def demo():
    root = tk.Tk()
    Pad(root).pack(expand=1, fill="both")
    root.mainloop()


if __name__ == "__main__":
    demo()

If you don't know what sel.first and sel.last are, check out this post or this reference.

I have made a chat client. I highlighted certain parts of the conversation using a custom quite easy to use Text widget that allows you to apply tags using regular expressions. It was based on the following post: How to highlight text in a tkinter Text widget .

Here you have an example of use:

# "text" is a Tkinter Text

# configuring a tag with a certain style (font color)
text.tag_configure("red", foreground="red")

# apply the tag "red" 
text.highlight_pattern("word", "red")

Have a look at this example:

from tkinter import *

root = Tk()

text = Text(root)
text.insert(INSERT, "Hello, world!\n")
text.insert(END, "This is a phrase.\n")
text.insert(END, "Bye bye...")
text.pack(expand=1, fill=BOTH)

# adding a tag to a part of text specifying the indices
text.tag_add("start", "1.8", "1.13")
text.tag_config("start", background="black", foreground="yellow")

root.mainloop()

I was able to change the color of the text for every match of a regex using the custom tkinter widget Text to get an event similiar to a 'text_changed':

import tkinter as tk

class CustomText(tk.Text):

def __init__(self, *args, **kwargs):
    """A text widget that report on internal widget commands"""
    tk.Text.__init__(self, *args, **kwargs)

    # create a proxy for the underlying widget
    self._orig = self._w + "_orig"
    self.tk.call("rename", self._w, self._orig)
    self.tk.createcommand(self._w, self._proxy)

def _proxy(self, command, *args):
    cmd = (self._orig, command) + args
    result = self.tk.call(cmd)
    if command in ("insert", "delete", "replace"):
        self.event_generate("<<TextModified>>")
    return result

And then, use it like that:

scr = CustomText(w)
scr.tag_configure('red', foreground = 'red')
scr.tag_configure('purple', foreground = '#a820a1')
scr.bind('<<TextModified>>', self.__textchanged__)

def __textchanged__(self, evt):
    for tag in evt.widget.tag_names():
        evt.widget.tag_remove(tag, '1.0', 'end')
    lines = evt.widget.get('1.0', 'end-1c').split('\n')
    for i, line in enumerate(lines):
        self.__applytag__(i, line, 'red', 'while|if', evt,widget) # your tags here
        self.__applytag__(i, line, 'purple', 'True', evt.widget)  # with a regex

@staticmethod
def __applytag__ (line, text, tag, regex, widget):
    indexes = [(m.start(), m.end()) for m in re.finditer(regex, text)]
    for x in indexes:
        widget.tag_add(tag, f'{line+1}.{x[0]}', f'{line+1}.{x[1]}')

Sorry friend! You can change fonts and other things of text widget using tag_config, but color I tried failed.

text.tag_configure("warning", fg="yellow") _tkinter.tclError: bitmap "yellow" is not definedp

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM