Найти - Пользователи
Полная версия: Моноширинный шрифт для виджета в PySide6
Начало » GUI » Моноширинный шрифт для виджета в PySide6
1 2
jcxz
Имею виджет с собственной отрисовкой (paintEvent). Текст в нём печатается при помощи QPainter.drawText().

Изначально я работал с PyQt5. Всё было ок - ставил шрифт QtGui.QFont(“Courier”) и отрисовка происходила корректно.
Но, по требованию работодателя (из-за ограничений лицензии на PyQt5), пришлось перейти на PySide6. Возникло ряд проблем. Почти все из них удалось решить, кроме пары проблем. Одна из нерешённых: Не удаётся подобрать моноширинный шрифт. Шрифт “Courier” ведёт себя не как моноширинный. Что очень странно. Пробовал и другие шрифты, которые должны быть моноширинными - ситуация аналогичная.
Простой тестовый код:
def paintEvent(paintEvent(self, ev):
qp = QtGui.QPainter()
...
fm = qp.fontMetrics()
s = '.'
for j in range(2):
c = 0
for i in range(1, 16):
c0 = c
c = fm.horizontalAdvance(s * i)
print("'{:s}': {:3d}, {:2d}".format(s, c, c - c0))
s = 'W'
С установленным шрифтом “Courier” выдаёт для PySide6 странный результат:
'.':   7,  7
'.': 14, 7
'.': 22, 8
'.': 29, 7
'.': 36, 7
'.': 43, 7
'.': 50, 7
'.': 58, 8
'.': 65, 7
'.': 72, 7
'.': 79, 7
'.': 86, 7
'.': 93, 7
'.': 101, 8
'.': 108, 7
'W': 7, 7
'W': 14, 7
'W': 22, 8
'W': 29, 7
'W': 36, 7
'W': 43, 7
'W': 50, 7
'W': 58, 8
'W': 65, 7
'W': 72, 7
'W': 79, 7
'W': 86, 7
'W': 93, 7
'W': 101, 8
'W': 108, 7
В то время как для PyQt5 он выдаёт корректный результат:
'.':   8,  8
'.': 16, 8
'.': 24, 8
'.': 32, 8
'.': 40, 8
'.': 48, 8
'.': 56, 8
'.': 64, 8
'.': 72, 8
'.': 80, 8
'.': 88, 8
'.': 96, 8
'.': 104, 8
'.': 112, 8
'.': 120, 8
'W': 8, 8
'W': 16, 8
'W': 24, 8
'W': 32, 8
'W': 40, 8
'W': 48, 8
'W': 56, 8
'W': 64, 8
'W': 72, 8
'W': 80, 8
'W': 88, 8
'W': 96, 8
'W': 104, 8
'W': 112, 8
'W': 120, 8

Почему так? Получается, что в PySide6 ширина символов варьируется в зависимости от позиции в строке??? =-O
И как всё-таки задать корректный моноширинный шрифт в PySide6? Есть такая возможность вообще? В инете искал долго - ничего вменяемого по этому вопросу не нашёл.
Или может QPainter нужно как-то пнуть, чтобы он рисовал текст правильно?

PS: Прошу сильно не пинать если что не так сказал - в Python-е я новичок.
Rodegast
> Но, по требованию работодателя

Откуда взялся работодатель который PySide использует?

> Получается, что в PySide6 ширина символов варьируется в зависимости от позиции в строке???

У тебя поменялась версия Qt, а там похоже начали при расчётах использовать дробные числа вот и ошибка в округлении. Если для тебя это критично, то установи размер шрифта через setPixelSize кратным 5 и будет счастье.
jcxz
Rodegast
У тебя поменялась версия Qt, а там похоже начали при расчётах использовать дробные числа вот и ошибка в округлении.
Очень сомнительно что это какая-то “ошибка округления”. Внимательно посмотрите на периодичность повтора: Изменения размера происходят то через 3, то через 4, то через 5 символов. При ошибке округления болталось бы между двумя соседними значениями.

PS: Проверил на тексте в QTextEdit с моноширинным шрифтом - картина аналогичная. Подозреваю - это проявляется во всех виджетах.
Неужто никто не использует моноширинные шрифты??? И никто не заметил такого заметного бага…
Rodegast
> При ошибке округления болталось бы между двумя соседними значениями.

И с чего ты это взял?

> И никто не заметил такого заметного бага…

Такой себе баг. Моноширинный шрифт это про одинаковую ширину символов, то что в некоторых позициях межсимвольный интервал меньше на 1 px мало кого волнует.
Ну и напиши про это разработчикам Qt-а, не надо ждать что кто то что то заметит.
jcxz
Rodegast
> При ошибке округления болталось бы между двумя соседними значениями.И с чего ты это взял?
С того, что “округление” выполняется до ближайшего меньшего или большего значения. И выполняется всегда в одну сторону (если делается неявно).
Что это за “округление” такое, что прыгает через значение?
Rodegast
> Что это за “округление” такое, что прыгает через значение?

Алгоритм расчёта длины строки в Qt это не просто деление или умножение двух чисел
jcxz
Просто - была надежда, что есть некий волшебный пендель, выписав который PySide-у, расчёт ширины таки станет простым умножением/делением.
Ведь PyQt так и делает (даже без пенделей) и не жужжит….
Rodegast
> была надежда, что есть некий волшебный пендель, выписав который PySide-у, расчёт ширины таки станет простым умножением/делением.

Если для тебя это критично, то установи размер шрифта через setPixelSize кратным 5 и будет счастье.
jcxz
Rodegast
Если для тебя это критично, то установи размер шрифта через setPixelSize кратным 5 и будет счастье.
Да, так работает. Спасибо.

Но уже решил проблему, сформировав таблицу преобразования ширина_окна->число_символов. Для всех ширин окна.

PS: А насколько это гарантированно (через кратность 5-ти)? Не перестанет ли работать в след. версии библиотек?
Rodegast
> Но уже решил проблему, сформировав таблицу преобразования ширина_окна->число_символов. Для всех ширин окна.

У меня такое ощущение что ты что то не то делаешь. Я месяца 4 назад выкладывал скриншот своей поделки с PySide6. Там как раз в основном отрисовка моноширинных текстов на схеме и никаких проблем из за неправильной ширины я не заметил. https://www.linux.org.ru/gallery/screenshots/17552363

> А насколько это гарантированно (через кратность 5-ти)? Не перестанет ли работать в след. версии библиотек?

До Qt7 думаю что доживёт, а дальше ХЗ.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB