Я использую Windows 11 и Python 3.11.1. Некоторые символы Юникода меняют внешний вид в зависимости от того, какой символ используется первым в tkinter для каждого шрифта. Код ниже показывает поведение:
import tkinter as tk
from tkinter.font import Font
app = tk.Tk()
tk.Label(app, text = "\u25b6 \u23EE \u270E", font=Font()).pack(side = "top")
tk.Label(app, text = "\u23EE \u25b6 \u270E", font=Font()).pack(side = "top")
app.mainloop()
Вывод следующий:
Почему это происходит? Есть ли способ установить внешний вид символов по умолчанию в шрифте без предварительного добавления временного символа?
Причина, по которой я использовал font=Font()
, это просто пример, это может быть font = "Arial 10"
или что-то еще. Символ Юникода, который используется первым, задает стиль для всех остальных символов Юникода в том же шрифте. Когда шрифт не установлен, он будет использовать TkDefaultFont
, и происходит то же самое, но это можно увидеть, только если две строки tk.Label(...)
переключаются между запусками.
Нет, это не так: использование font = "Arial 10"
(или лучше font=("Arial", 10)
) делает именно то, что вы ожидаете, показывая одни и те же символы независимо от порядка.
Если вы запустите тот же код, но измените шрифт в первом на ("Arial", 10)
, а во втором на ("Arial", 11)
, то символы будут отличаться. Если вы используете ("Arial", 10)
дважды, во второй раз он вернется к тому же шрифту, и тогда форма символа Юникода будет такой же.
Я провел несколько тестов и, в конце концов, попробовав символы юникода в Google Chrome, я понял, что эта проблема не имеет ничего общего с tkinter или Python. Кажется, это большая проблема с символами Юникода в целом. Вот что произойдет, если вы поиграетесь со следующими символами Юникода (⏮▶▶) в строке поиска Google Chrome.
Редактировать:
Как отметил Майк «Pomax» Камерманс, эта проблема не возникает при использовании шрифта, который поддерживает все используемые символы Юникода. Например, GNU Unifont, http://unifoundry.com/unifont/, поддерживает символы Юникода, упомянутые в вопросе, и форма этих символов всегда одинакова при использовании этого шрифта.
Наиболее вероятная причина, по которой это происходит, зависит от того, какой символ Юникода используется первым, а затем используются разные резервные шрифты, и поэтому форма может отличаться.
Это связано с тем, «что отвечает за выбор шрифта». Если я запускаю ваш код с указанным фактическим шрифтом (с поддержкой используемых кодовых точек), замена смайликов не происходит, независимо от порядка.
Да, это кажется разумным, вы нашли шрифт, поддерживающий эти символы? Если да, то я хотел бы проверить это.
Что вы имеете в виду под "этими"? Синие или черные?
Синие и черные используют одни и те же символы Юникода, но показаны в tkinter и google chrome, хотя в последнем перо не использовалось. Я протестировал GNU Unifont, и тогда эта проблема не появилась. Как вы упомянули, пока символ юникода поддерживается выбранным шрифтом, проблем нет, но если текущий шрифт его не поддерживает, то в зависимости от того, к какому шрифту он возвращается, форма может отличаться.
Это полностью зависит от ОС, в которой работает ваш скрипт, и установленных шрифтов, но вы упомянули Arial в комментариях к своему сообщению, и Arial на самом деле является одним из шрифтов, которые отлично работают.
Я создал этот фрагмент кода: goonlinetools.com/snapshot/code/#rqwz9s881cepd9gd4p6e5 для меня это генерирует совершенно разные символы при использовании одних и тех же символов Юникода и Arial.
Верно, но здесь вы показываете, что один и тот же шрифт для одних и тех же символов при разных размерах шрифта дает разные результаты. Что сильно отличается от вашего поста. Кроме того, если вы поменяете местами третью и четвертую метки, внезапно все снова отобразится по-другому, так что на данный момент это почти наверняка ошибка, о которой вы должны сообщить мейнтейнерам tk.
Если бы вы переключили размеры, вы бы увидели, что они не имеют значения, причина появления этой проблемы (моя гипотеза) заключается в том, что при первом создании шрифта они не выбрали резервные шрифты, но когда они были установлены один раз, они будет по-прежнему иметь тот же резервный шрифт. То же самое происходит для нескольких приложений, например, VSCode при наведении курсора на переменную с этими символами, Google Chrome, Edge, Slack. Вот почему я не думаю, что это ошибка в tkinter.
Я поменял размеры. Это достаточно странно, и если бы я нашел это, я бы сообщил об этом как об ошибке. Даже если вы оставите этот вопрос открытым (но затем обновите его с помощью этого нового кода, чтобы показать конкретный пример того, что происходит не так), его следует зарегистрировать, чтобы единственные люди могли действительно это исправить, знали, что что-то нужно исправить.
Я разместил эту проблему на: github.com/python/cpython/issues/101032
обратите внимание, что в этом коде оба arial имеют размер 32, вы, вероятно, захотите сделать arial2 размером 33, как в примере, который вы показали мне выше, и включить скриншот того, как выглядит результат.
Это не связано с тем, какой символ используется первым. Это вызвано опцией
font=Font()
. Удалениеfont=Font()
из обоихtk.Label(...)
даст правильный результат.