Tkinter — динамическое изменение размера шрифта

Я почти все перепробовал и везде искал, как динамически менять шрифты в виджете Text(). Я не хочу, чтобы весь текст в виджете Text() менялся только на текст, который набирается после изменения размера шрифта, например страницы или слова и т. д.

Вот что я представлял, будет работать:

#in the __init__ function
    sizesList = [8, 10, 12, 13, 14, 16, 18, 22, 26, 32, 40]
    var = IntVar()
    var.set(13)
    self.fontsizeDropDown = OptionMenu(self.toolbarFrame, var, *sizesList, command=self.fontSizeFunc)
    self.fontsizeDropDown.grid(row=0, column=1, sticky=N)

def fontSizeFunc(self, var):
    theFont = "Arial %d" % var
    self.textentry.tag_add('texthere', INSERT, INSERT)
    self.textentry.tag_config('texthere', font=theFont)

Однако все, что он делает, это меняет размер буквы после курсора, только если там есть буква, тогда любой дальнейший набор текста возвращается к исходному размеру шрифта.


person Kyle    schedule 09.12.2015    source источник
comment
Попробуйте изменить второй INSERT на END, чтобы вы печатали внутри настроенного тега.   -  person Terry Jan Reedy    schedule 10.12.2015
comment
@TerryJanReedy Я тоже так пробовал, размер курсора меняется и остается с указанным размером шрифта, однако печатный текст остается размером по умолчанию. Затем, когда я перемещаю курсор в середине текста и меняю размер шрифта, текст от курсора до конца текста изменяется на указанный размер.   -  person Kyle    schedule 11.12.2015


Ответы (1)


ИЗМЕНИТЬ:

Выяснил другой способ сделать это, который мне больше понравился, поэтому поместил его сверху со старым ниже в качестве ссылки.

НОВАЯ ВЕРСИЯ:

Код должен отслеживать, где начинается и заканчивается индекс тега. Это также будет уникальное имя тега для каждого размера шрифта. Я подумал, что хорошее имя тега может быть таким же, как шрифт и размер, используемые для конфигурации тега.

Когда выбран новый размер шрифта, написанный текст получит тег с начальным и конечным индексом, настроенным с правильным размером шрифта. Затем он установит новый размер шрифта, установит его для текстового виджета и обновит переменные. Тег не будет добавлен, пока вы снова не измените размер шрифта. Но так как текстовый виджет имеет текущий выбранный размер шрифта, он будет отображаться с правильным размером.

import sys
import tkinter as tk
from tkinter import ttk


def main():
    def current_index():
        # Return current cursor position in the text widget
        return textentry.index(tk.INSERT)

    def fontSizeFunc(*new_var):
        # Set the tag for the text that has been written
        textentry.tag_add(current_tag.get(), start_index.get(), current_index())
        textentry.tag_config(current_tag.get(), font=current_tag.get())

        # Sets new Font Size, store start_index position for new tag,
        # create a new tag that has theFont as tag name
        theFont = "Arial %d" % new_var
        textentry.configure(font=theFont)
        start_index.set(current_index())
        current_tag.set(theFont)

    # Simple Tkinter setup for testing purpose
    root = tk.Tk()

    sizesList = [8, 10, 12, 13, 14, 16, 18, 22, 26, 32, 40]
    var = tk.IntVar()
    var.set(13)

    frame = ttk.Frame(root)
    frame.grid(column=0, row=0)
    fontsizeDropDown = tk.OptionMenu(frame, var, *sizesList, command=fontSizeFunc)
    fontsizeDropDown.grid(row=0, column=1, sticky=tk.N)
    textentry = tk.Text(frame)
    textentry.grid(row=1, column=0, columnspan=2)

    # Initialize start_index and current_tag
    start_index = tk.StringVar()
    current_tag = tk.StringVar()
    start_index.set(current_index())
    current_tag.set("Arial %d" % var.get())

    root.mainloop()

if __name__ == '__main__':
    sys.exit(main())

Если вы хотите сохранить текст в текстовом виджете, не забудьте установить тег, вызвав fontSizeFunc() перед выходом/сохранением. Или последний введенный текст будет без тега.

СТАРАЯ ВЕРСИЯ:

Я подумал, что если вы хотите иметь динамические изменения, вам нужно будет проверить текстовый виджет на наличие изменений. И каждый раз, когда вы меняете размер шрифта в меню параметров, вы создаете новый тег.

В приведенном ниже примере кода он проверяет KeyRelease, когда текстовый виджет находится в фокусе. Текущий индекс тега будет расширяться по мере ввода, а при выборе нового размера шрифта будет создан новый тег. Использовал ваш код везде, где мог, просто настроил его так, чтобы он работал, не посещая занятия.

import sys
import tkinter as tk
from tkinter import ttk


def main():
    def text_changes(*event):
        # On every KeyRelease with the Text widget in focus,
        # it get the current tag, start index and current index.
        theFont = "Arial %d" % var.get()
        textentry.tag_add(current_tag.get(), start_index.get(), current_index())
        textentry.tag_config(current_tag.get(), font=theFont)

    def current_index():
        # Return current cursor position in the text widget
        return textentry.index(tk.INSERT)

    def fontSizeFunc(*new_var):
        # Create a new tag with a new start index / position
        start_index.set(current_index())
        current_tag.set(current_index())

    # Simple Tkinter setup for testing purpose
    root = tk.Tk()

    sizesList = [8, 10, 12, 13, 14, 16, 18, 22, 26, 32, 40]
    var = tk.IntVar()
    var.set(13)

    frame = ttk.Frame(root)
    frame.grid(column=0, row=0)
    fontsizeDropDown = tk.OptionMenu(frame, var, *sizesList, command=fontSizeFunc)
    fontsizeDropDown.grid(row=0, column=1, sticky=tk.N)
    textentry = tk.Text(frame)
    textentry.grid(row=1, column=0, columnspan=2)

    # Initialize start_index and current_tag
    start_index = tk.StringVar()
    current_tag = tk.StringVar()
    start_index.set(current_index())
    current_tag.set(current_index())

    # When the text entry has focus, every key release will run the
    # text_changes function
    textentry.bind('<KeyRelease>', text_changes)

    root.mainloop()

if __name__ == '__main__':
    sys.exit(main())

Надеюсь, вы сможете использовать это, чтобы создать свою собственную лучшую версию :)

person oystein-hr    schedule 14.12.2015