![]() |
|
|
![]()
|
|
| wowka19 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 285 Регистрация: 30.11.2011 Репутация: нет Всего: нет |
Необходимо размещать на сцене текст со следующим функционалом:
1. Редактировать сам текст на самой сцене (как в фотошопе: кликаешь на надпись и редактируешь) 2. Менять цвет, size, B, I и сам шрифт (Arial,...) - тут проблем возникнуть не должно 3. Менять расстояние между символами, не меняя других параметров 4. Изгибать надписи по дуге 5. Вращать надпись - тут тоже без проблем Вопрос: что брать QGraphicsSimpleTextItem или QGraphicsTextItem и как реализовать 1, 3 и 4 пункты? |
|||
|
||||
| Amp |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 886 Регистрация: 17.2.2009 Репутация: 7 Всего: 17 |
Писать свой рендер
Это сообщение отредактировал(а) Amp - 22.4.2014, 15:36 |
|||
|
||||
| wowka19 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 285 Регистрация: 30.11.2011 Репутация: нет Всего: нет |
после ввода. А без своего рендера никак? Неужели QGraphicsTextItem нельзя согнуть по дуге? И если все-таки писать рендер, то что брать за основу - QGraphicsItem? Это сообщение отредактировал(а) wowka19 - 22.4.2014, 17:13 |
|||
|
||||
| Amp |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 886 Регистрация: 17.2.2009 Репутация: 7 Всего: 17 |
Задача ведь нетривиальная. QGraphicsTextItem рендерит через QTextLayout, там такой акробатики нет. Изначально я бы создавал QGraphicsTextItem, так как там, насколько я вижу, есть in-place редактирование. А после, если применяется преобразвание, подменял бы на свой наследник от QGraphicsItem. Впрочем говорю навскидку - со сценграфом этим плотно не работал.
|
|||
|
||||
| wowka19 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 285 Регистрация: 30.11.2011 Репутация: нет Всего: нет |
Подскажи как мне в QGraphicsItem::paint() поворачивать символ ? не создавать же мне на каждый символ дочерний QGraphicsItem, чтобы только повернуть его штатным QGraphicsItem::rotate() ?
|
|||
|
||||
| Amp |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 886 Регистрация: 17.2.2009 Репутация: 7 Всего: 17 |
Устанавливать нужную матрицу транформации у QPainter (через rotate/translate или setTransform) перед отрисовкой каждого символа. Посмотри, например, здесь пример http://stackoverflow.com/questions/1775365...-qpainter-class
|
|||
|
||||
| wowka19 |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 285 Регистрация: 30.11.2011 Репутация: нет Всего: нет |
С матрицами в QPainter уже разобрался. Но уточню:
это
и это
одно и тоже? т.е. painter1.transform() == painter2.transform() ??? не считая погрешности double конечно же Приведенный тобой пример уже видел. Но не пойму как мне гибко регулировать расстояние между символами, чтобы они не наезжали друг на друга в независимости от шрифта/размера и т.д? Т.е. за что мне уцепиться, за какой параметр QFont'а? Это сообщение отредактировал(а) wowka19 - 22.4.2014, 22:22 |
||||
|
|||||
| Amp |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 886 Регистрация: 17.2.2009 Репутация: 7 Всего: 17 |
Да, одно и то же. Причем второй вариант теоретически более предпочтителен, так как не нужно будет на отрисовку каждой буквы дергать save/restore - painter меньше лишних действий будет совершать.
Цепляться надо к QFontMetrics, получая размер каждого отдельного символа и, исходя из этого, считать их положения. К тому же это потом поможет высчитать верно bounding rect итоговой надписи. |
|||
|
||||
| wowka19 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 285 Регистрация: 30.11.2011 Репутация: нет Всего: нет |
Вот код рендера текста по дуге на QPixmap:
в итоге с учетом ширины символа стало лучше, но некоторые буквы всеравно немного "скачут", как по вертикали так и по горизонтали. Что не так? И сразу второй вопрос: как мне грамотно (без оверхеда) вычислить размеры области редеринга (QPixmap pixmap_(?,?)), если я уже рендерю в него, не имея данных о конечных размерах вплоть до конца рендеринга? И еще текст получается несглаженным, хотя все флаги стоят. Это из-за того, что я его при рендеринге перемножаю на матрицу textMatrix по нескольку раз. Т.е, "растеризовав" первый символ (тем самым превратив его в маленькую картинку), я перемножаю ее (картинку) на матрицу textMatrix еще несколько раз (кол-во символов - 1). Более того, итоговую надпись (т.е. полученный QPixmap) еще нужно будет вращать на сцене, что также плохо отразиться на качестве надписи. Глядя на неизменно отличное качество QGraphicsSimpleTextItem и QGraphicsTextItem при любых манипуляциях складывается подозрение, что символы рендерятся спец. встроенным движком, который принимает конечную матрицу преобразований (вплоть до матрицы вида), перемножает на нее символ еще в векторном виде, и только потом растеризует, выдавая его в том виде, в котором его должен увидеть пользователь. Отсюда вопрос как заполучить или реализовать (лучше заполучить) этот механизм себе в класс MMSpecialTextItem? Это сообщение отредактировал(а) wowka19 - 25.4.2014, 09:10 |
|||
|
||||
| Amp |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 886 Регистрация: 17.2.2009 Репутация: 7 Всего: 17 |
1. QFontMetrics лучше получать из текущего QPainter-а.
2. Трансформацию рассчитываешь очень странно. Угол зависит от длины текста (количества букв), радиуса окружности и текущего символа (его номера). 3. У setWorldTransform второй аргумент должен быть false Грамотно и точно без оверхеда не выйдет - придется выполнить холостой прогон без отрисовки, вычисляя границы. С другой стороны, если радиус окружности заранее известен, то на основе его и размера шрифта можно, хоть и не совсем точно, посчитать размер битмапа, который будет необходим для отрисовки. Не знаю что ты именно вкладываешь в понятие "несглаженный" (нет пока возможности собрать код) - приложи скриншот. |
|||
|
||||
| wowka19 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 285 Регистрация: 30.11.2011 Репутация: нет Всего: нет |
1. Сомневаюсь, что что-то изменится, так как QPainter::fontMetrics возвращает параметры текущего шрифта, который устанавливаю я явным образом. Более того, от QFont можно получить QFontMetricsF, что точнее. Немного скачущий текст оказался следствием того, что почемуто QFontMetricsF::width("т") (именно русской наклонной жирной маленькой "т" шрифта Times New Roman) в полтора раза больше остальных (не всех) букв. Понятное дело что "т" шире чем например "к" но не в 1.5 раз. Но это мелочи - я забил.
2. Да, угол всей надписи действительно зависит от количества букв, но этот факт при вычислении позиции конкретного символа никак не поможет. Я высчитываю угол (дельту) для каждого символа так как их ширина различна для символов. И делаю это, исходя из, естественно, ширины символа (чем шире символ, тем больше угол) и из радиуса (чем больше радиус, тем меньше нужен угол для поворота). Отсюда и формула (немного школьной геометрии и алгебры): arctg( ширина_символа / радиус ) - в радианах. 3. У setWorldTransform второй аргумент не должен быть false, ведь иначе я буду отменять предыдущие повороты (для уже отрисованных символов) и рисовать примерно в том же месте все символы. По сути у меня остался один вопрос: как рисовать символы уже с учетом матричных преобразований, т.е. чтобы текстовый движок, который оперирует векторными данными шрифта (в моем случае Times New Roman) сначала учитывал матрицу преобразований, а потом уже проводил растеризацию. У меня же получается, что матрица накладывается уже на отрендеренный символ. Посмотри какие четкие шрифты выводят QGraphicsSimpleTextItem и QGraphicsTextItem. Подумываю просто сделать обычный QGraphicsItem и напихать в него коллекцию дочерних QGraphicsSimpleTextItem... |
|||
|
||||
| math64 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 23 Всего: 72 |
Для наклонного шрифта сумма ширин отдельных букв больше, чем ширина всего текста - отсюда и разница.
Кстати, можно делать более точную транформацию - из прямоугольника в трапецию (матрица вычисляется с помощью quadToQuad() ) [для наклонного шрифта нужно преобразовывать параллелограмм] |
|||
|
||||
| Amp |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 886 Регистрация: 17.2.2009 Репутация: 7 Всего: 17 |
Можешь попробовать глифы предварительно конвертировать в path и потом уже рисовать (выставляя QPen(Qt.NoPen)). Результат должен быть лучше.
Присоединённый файл ( Кол-во скачиваний: 8 )
2014_04_28_13_19_09_python.png 21,75 Kb |
|||
|
||||
| wowka19 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 285 Регистрация: 30.11.2011 Репутация: нет Всего: нет |
спасибо.
Есть еще вопрос по расстоянию между символами. Я устанавливаю его так: font.setLetterSpacing(QFont::AbsoluteSpacing, 40); Все бы хорошо, но мне не нужен этот промежуток перед знаками препинания. Есть ли простое решение? Это сообщение отредактировал(а) wowka19 - 30.4.2014, 13:46 |
|||
|
||||
| wowka19 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 285 Регистрация: 30.11.2011 Репутация: нет Всего: нет |
ап (предыдущий пост) и еще одна проблема:
Текст на сцене в виде QPixmap отлично смотрится только если не использовать QGraphicsView::scale(), т.е. масштабирование вида. При увеличении видны пиксели - но не это меня волнует. Проблема возникает при уменьшении - тонкие элементы текста съедаются алгоритмом масштабирования. Как решить проблему (например с QGraphicsSimpleTextItem такого не происходит)? |
|||
|
||||
![]()
|
| Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |