Действительно пользовательский шрифт в Tkinter
Я делаю интерфейс в Tkinter, и мне нужно иметь пользовательские шрифты. Не только, скажем, Helvetica в определенном размере или что-то еще, кроме шрифтов, отличных от того, что обычно доступно на любой данной платформе. Это будет то, что будет храниться в программе как файл изображения или (предпочтительно) файл шрифта Truetype или аналогичный. Я не хочу устанавливать нужные шрифты на всех машинах, которые будут использовать эту программу, я просто хочу их переносить с помощью программы в том же каталоге.
Модуль tkFont выглядит так, как будто он должен сделать что-то вроде этого, но я не могу понять, где будет искать имя файла для шрифта, который обычно не доступен для системы, запускающей программу. Заранее благодарим за помощь.
Ответы
Ответ 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