简体   繁体   中英

How to only change font size of text widget in tkinter(not family)

I am trying to make a text editor in tkinter.

I am changing the font size and font family on tag attributes but the problem is when I change font family the size of the selected text returns to default and when i change the size the font family returns to default. I have tried many things

def changeFontSize2():
     textPad.tag_add("bt2", "sel.first", "sel.last")
     textPad.tag_config("bt2",font = (False,2))

def changeFontSize6():
     textPad.tag_add("bt6", "sel.first", "sel.last")
     textPad.tag_config("bt6",font = (False,6))

def changeFontFamily1():
     textPad.tag_add("btArial", "sel.first", "sel.last")
     textPad.tag_config("btArial",font = ("Arial",False))

def changeFontFamily2():
      textPad.tag_add("btCourierNew", "sel.first", "sel.last")
      textPad.tag_config("btCourierNew",font = ("Courier New",False))

If you want to configure a font to be exactly like an existing font but with some slight changes, you can create a new font object based off of an existing font, and then configure the attributes of that new font object.

For example:

...
import tkinter.font as tkFont
...

def changeFontSize2():
    textPad.tag_add("bt2", "sel.first", "sel.last")

    new_font = tkFont.Font(font=textPad.cget("font"))
    size = new_font.actual()["size"]
    new_font.configure(size=size+2)
    textPad.tag_config("bt2", font=new_font)

However , doing it exactly like the above will cause a memory leak, since you are creating new font objects every time the function is called. It would be better to either create all of your fonts up front, or come up with a way of creating the fonts on the fly and then cacheing them, so you only create each font once.

Example:

fonts = {}
...
def changeFontSize2():
    name = "bt2"
    textPad.tag_add("bt2", "sel.first", "sel.last")

    if name not in fonts:
        fonts[name] = tkFont.Font(font=textPad.cget("font"))
        size = fonts[name].actual()["size"]
        fonts[name].configure(size=size+2)
        textPad.tag_configure(name, font=fonts[name])

My advice is to create the fonts and tags once at the start of your program rather than creating them on the fly.

fonts = {
    "default": tkFont.Font(family="Helvetica", size=12),
    "bt2": tkFont.Font(family="Helvetica", size=14),
    "btArial", tkFont.Font(family="Arial", size=12),
    ...
}
textPad.configure(font=fonts["default"])
textPad.tag_configure("bt2", font=fonts["bt2"])
textPad.tag_configure("btArial", font=fonts["btArial"])
...
def changeFontSize2():
    textPad.tag_add("bt2", "sel.first", "sel.last")

The tkinter font objects are very powerful. Once you've created the font and are using it, if you reconfigure the font (eg: fonts["bt2"].configure(family="Courier") ), every place that uses that font will instantly be updated to use the new configuration.

As you said, there are many ways to achieve the desired effect. Since there are no other options presented after many hours, here is one that works anyway. I centralized the formatting of the font to one function and call it with different arguments from the various buttons.

def setSelTagFont(family, size):
    curr_font = textPad.tag_cget('sel', "font")
    # Set default font information
    if len(curr_font) == 0:
        font_info = ('TkFixedFont', 10)
    elif curr_font.startswith('{'):
        font_info = curr_font.replace('{','').replace('} ','.').split('.')
    else:
        font_info = curr_font.split()

    # Apply requested font attributes
    if family != 'na':
        font_info = (family, font_info[1])
    if str(size) != 'na':
        font_info = (font_info[0], size)
    textPad.tag_config('sel', font=font_info)
    print("Updated font to:", font_info)

root = Tk()
textPad = Text(root)
textPad.pack()
textPad.insert(1.0, "Test text for font attibutes")
textPad.tag_add("sel", 1.0, END + '-1c')
textPad.focus_set()
frame = Frame(root)
frame.pack()
Button(frame, text="Size 2", command=lambda: setSelTagFont('na', 2)).pack(side='left',padx=2)
Button(frame, text="Size 6", command=lambda: setSelTagFont('na', 6)).pack(side='left',padx=2)
Button(frame, text="Family 1", command=lambda: setSelTagFont('Arial', 'na')).pack(side='left',padx=2)
Button(frame, text="Family 2", command=lambda: setSelTagFont('Courier New', 'na')).pack(side='left',padx=2)
root.mainloop()

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