pythonuser-interfacetkintertkinter-text

Adding Multiple Tags Tkinter Text


I am making a tkinter text editor. I'm trying to make it so that the user can press Control+b for bold text, Control+i for italic text, etc. One problem with this is overlapping tags. When I add two tags, one on top of another, like a bold tag and an italic tag, they overwrite each other. I have looked over SO for answers, and I cobbled this together from them. Is there a better way than below? Select any text and press Control+b or Control+u.

from tkinter import *
from tkinter.ttk import *
from tkinter.font import *   


class MyText(Text):

    def __init__(self):
        Text.__init__(self, font=("Montserrat", 12))

        self.edit_bold = False
        self.edit_underline = False

        self.tags = []

        self.bind("<Control-b>", self.on_format)
        self.bind("<Control-u>", self.on_format)

    def on_format(self, event):
        if event.keysym == "b": self.edit_bold = not self.edit_bold
        if event.keysym == "u": self.edit_underline = not self.edit_underline

        if self.edit_bold: edit_bold = "bold"
        else: edit_bold = "normal"

        tagname = f"{edit_bold}-{self.edit_underline}"

        font = Font(family="Montserrat", size=12, weight=edit_bold)

        for tag in self.tag_names(SEL_FIRST):
            self.tag_delete(tag)

        if not tagname in self.tag_names():
            self.tag_configure(tagname, font=font, underline=self.edit_underline)

            self.tag_add(tagname, SEL_FIRST, SEL_LAST)

            print(self.tag_names())

        else:
            self.tag_configure(tagname, font=font)

        return "break"



application = Tk()
text = MyText()
text.pack()

application.mainloop()

Solution

  • After hours of hours research, I found a solution. Hope someone be helped by this answer.

    You have to keep update your project after pressing 'bold' and 'italic' buttons. just see an example.

    Bold Text

    def bold_it(self):
        try:
            # Create our font
            self.bold_font = font.Font(self.text_editor, self.text_editor.cget("font"))
            self.bold_font.configure(weight="bold")
            self.italic_font = font.Font(self.text_editor, self.text_editor.cget("font"))
            self.italic_font.configure(slant='italic')
    
            # Configure a tag
            self.text_editor.tag_configure("bold", font=self.bold_font)
            self.text_editor.tag_configure("italic", font=self.italic_font)
    
            # Define Current tags
            current_tags = self.text_editor.tag_names("sel.first")
            if "bold_italic" in current_tags:
                self.text_editor.tag_remove("bold_italic", "sel.first", "sel.last")
                self.text_editor.tag_add("bold", "sel.first", "sel.last")
                self.text_editor.tag_add("italic", "sel.first", "sel.last")
            
            current_tags = self.text_editor.tag_names("sel.first")
            # If statment to see if tag has been set
            if "bold" in current_tags:
                self.text_editor.tag_remove("bold", "sel.first", "sel.last")
            else:
                self.text_editor.tag_add("bold", "sel.first", "sel.last")
            self.update_text()
        except:
            pass
    

    Italics Text

    def italics_it(self):
        try:
            # Create our font
            italics_font = font.Font(self.text_editor, self.text_editor.cget("font"))
            italics_font.configure(slant="italic")
            bold_font = font.Font(self.text_editor, self.text_editor.cget("font"))
            bold_font.configure(weight='bold')
    
            # Configure a tag
            self.text_editor.tag_configure("italic", font=italics_font)
            self.text_editor.tag_configure("bold", font=bold_font)
    
            # Define Current tags
            current_tags = self.text_editor.tag_names("sel.first")
            
            # Define Current tags
            current_tags = self.text_editor.tag_names("sel.first")
            if "bold_italic" in current_tags:
                self.text_editor.tag_remove("bold_italic", "sel.first", "sel.last")
                self.text_editor.tag_add("italic", "sel.first", "sel.last")
                self.text_editor.tag_add("bold", "sel.first", "sel.last")
            
            current_tags = self.text_editor.tag_names("sel.first")
            # If statment to see if tag has been set
            if "italic" in current_tags:
                self.text_editor.tag_remove("italic", "sel.first", "sel.last")
            else:
                self.text_editor.tag_add("italic", "sel.first", "sel.last")
            self.update_text()
        except:
            pass
    

    Finally keep update your project.

     def update_text(self):
        # Create our font
        style_font = font.Font(self.text_editor, self.text_editor.cget("font"))
        style_font.configure(weight='bold', slant="italic")
    
        # Configure a tag
        self.text_editor.tag_configure("bold_italic", font=style_font)
    
        # Define Current tags
        current_tags = self.text_editor.tag_names("sel.first")
    
        # If statment to see if tag has been set
        if "bold" in current_tags and "italic" in current_tags:
            self.text_editor.tag_remove("italic", "sel.first", "sel.last")
            self.text_editor.tag_remove("bold", "sel.first", "sel.last")
            self.text_editor.tag_add("bold_italic", "sel.first", "sel.last")