Подтвердить что ты не робот

Действительно пользовательский шрифт в Tkinter

Я делаю интерфейс в Tkinter, и мне нужно иметь пользовательские шрифты. Не только, скажем, Helvetica в определенном размере или что-то еще, кроме шрифтов, отличных от того, что обычно доступно на любой данной платформе. Это будет то, что будет храниться в программе как файл изображения или (предпочтительно) файл шрифта Truetype или аналогичный. Я не хочу устанавливать нужные шрифты на всех машинах, которые будут использовать эту программу, я просто хочу их переносить с помощью программы в том же каталоге.

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

4b9b3361

Ответ 1

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

Я не мог найти способ использовать tkFont для импорта связанного шрифта на странице tkFont.

Ответ 2

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

Ответ 3

Существует способ получить внешние шрифты в Tkinter [Windows]

(по крайней мере, в Windows)

Ключом кода для выполнения этой работы является следующая функция:

from ctypes import windll, byref, create_unicode_buffer, create_string_buffer
FR_PRIVATE  = 0x10
FR_NOT_ENUM = 0x20

def loadfont(fontpath, private=True, enumerable=False):
    '''
    Makes fonts located in file `fontpath` available to the font system.

    `private`     if True, other processes cannot see this font, and this 
                  font will be unloaded when the process dies
    `enumerable`  if True, this font will appear when enumerating fonts

    See https://msdn.microsoft.com/en-us/library/dd183327(VS.85).aspx

    '''
    # This function was taken from
    # https://github.com/ifwe/digsby/blob/f5fe00244744aa131e07f09348d10563f3d8fa99/digsby/src/gui/native/win/winfonts.py#L15
    # This function is written for Python 2.x. For 3.x, you
    # have to convert the isinstance checks to bytes and str
    if isinstance(fontpath, str):
        pathbuf = create_string_buffer(fontpath)
        AddFontResourceEx = windll.gdi32.AddFontResourceExA
    elif isinstance(fontpath, unicode):
        pathbuf = create_unicode_buffer(fontpath)
        AddFontResourceEx = windll.gdi32.AddFontResourceExW
    else:
        raise TypeError('fontpath must be of type str or unicode')

    flags = (FR_PRIVATE if private else 0) | (FR_NOT_ENUM if not enumerable else 0)
    numFontsAdded = AddFontResourceEx(byref(pathbuf), flags, 0)
    return bool(numFontsAdded)

После вызова loadfont с указанием пути к файлу шрифта (который может быть любым из .fon, .fnt, .ttf, .ttc, .fot, .otf, .mmm, .pfb или .pfm), вы можете загрузить шрифт, как и любой другой установленный шрифт tkFont.Font(family=XXX, ...). и использовать его в любом месте. [Подробнее см. MSDN]

Самая большая оговорка здесь в том, что фамилия шрифта не обязательно будет именем файла; он встроен в данные шрифта. Вместо того, чтобы пытаться проанализировать имя, вероятно, было бы проще просто посмотреть его в графическом интерфейсе браузера шрифтов и жестком кодексе в ваше приложение. изменить: или, в соответствии с приведенным ниже замечанием patthoyt, найдите его в tkFont.families() (как последний элемент или, более надежно, путем сравнения списка семейств до и после загрузки шрифта).

Я нашел эту функцию в digsby (license); там существует функция unloadfont, если вы хотите удалить шрифт до завершения завершения вашей программы. (Вы также можете просто положиться на параметр private, чтобы выгрузить шрифт, когда закончится ваша программа.)

Для всех, кого интересует, здесь является обсуждение этой темы на [TCLCORE] несколько лет назад. Еще немного фона: шрифты в MSDN