![]() |
|
|
![]()
|
|
| Glad |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 27 Регистрация: 16.8.2005 Репутация: нет Всего: нет |
Доброго времени суток!
У меня задача нарисовать дорогу по модели(данные). Я нашёл(случайно) класс QGraphicsPathItem и все связанные с ним(QPainterPath, например). Но взглянув внутрь, как-то смутился.. Черепашья графика ? Зачем нужен этот класс ? И имеет ли он какие-нибудь преимущества над скажем QVector<QGraphicsLineItem> ? Заранее благодарю. |
|||
|
||||
| Amp |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 886 Регистрация: 17.2.2009 Репутация: 7 Всего: 17 |
QPainterPath позволяет создавать сложные контуры и кривые, комбинируя их из простых линий, дуг, кривых Безье, тестовых глифов и т.п. Полученный путь (path) можно сохранить и использовать (отрисовать) в будущем. Стандартная сущность для векторной графики (аналог, например, cairo_path_t в cairo). Все это конечно же можно аппроксимировать вручную линиями, сложив их в вектор, но это мартышкин труд с кучей недостатков. Например будут проблемы с заливкой, пересечениями контуров, соединениями между линиями (joins).
|
|||
|
||||
| Glad |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 27 Регистрация: 16.8.2005 Репутация: нет Всего: нет |
Вы знаете меня смутило несколько вещей в этом всём деле. Вот несколько из них:
* Каждый элемент Path это не обязательно фигура.. В частности, там возвращается тип объекта moveTo, что как-то странно(хотя в терминах черепашьей графики это нормально). * Селекшн не всегда работает правильно.. Я нарисовал тестовую ломанную с помощью этих инструментов и ломанная выделялась даже если я кликал мимо нее. Впрочем, определить алгоритм попадания я так и не смог: по началу я подумал что это просто попадание в BoundingBox ломанной, но потом потестировав и "потыкав" по экрану, понял что это не так. * Нет возможности выделять и редактировать элементы ломаной. Если я захочу выделить элемент ломаной и что-то с ним сделать(например, изменить толщину дороги в этом участке или сменить тип дороги с гравейки на асфальт) то этого не сделаешь с помощью этих инструментов(а может быть я их просто не знаю?). Вот как-то так.. Всё конечно зависит от решаемой задачи.. Если задача вывести буквы/цифры без возможности редактирования, то наверное этот инструмент подошёл как нельзя лучше. |
|||
|
||||
| Amp |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 886 Регистрация: 17.2.2009 Репутация: 7 Всего: 17 |
Фигуры - это комбинации линий и кривых. Например path в виде прямоугольника можно представить комбинацией одного moveTo и четырех lineTo вызовов. В итоге будет образован замкнутый контур, который мы сможем назвать фигурой. Методы addRect, addPolygon, addEllipse можно считать высокоуровневыми надстройками, которые в своей реализации все равно в итоге сводятся к последовательности из moveTo/lineTo/arcTo. Ну да, выходит, что бегает черепашка и оставляет за собой линию. В определенные моменты она может обравать линию и начинать рисовать новую (получаются sub path-ы в рамках одного path). Это все надо писать самому. К тому же нельзя изменить цвет или толщину какого-то отдельного учатка внутри path. Для Qt это один целый элемент, к которому применяется текущие настройки кистей и цвета. Не знаю в чем тут дело. |
|||
|
||||
| math64 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 23 Всего: 72 |
Это не черепашья графика. Черепашья графика - это когда изображение непросредственно выводится на монитор, что медленно и происходит мерцание экрана. В Qt обязательная двойная буферизация, как что мерцания не будет.
moveTo и lineTo - естественный способ задания кривой. В итоге это сводится к аналогичным вызовам Microsoft API. QPainterPath задает одну область, заливаемую одной кистью (хотя возможно, градиентной или пустой) и обводимой одним пером (хотя возможно, градиентным или пустым). Если нужно что-то выделить другим цветом, нужен второй QPainterPath. QPainterPath следует рассматривать как черный ящик. Хотя можно получить точки moveTo и lineTo, лучше их хранить где-то в своём классе. Выделение действительно, иногда ведёт себя не так, как хочется. В этом случае нужно писать своё выделение. |
|||
|
||||
| Glad |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 27 Регистрация: 16.8.2005 Репутация: нет Всего: нет |
А как это сделать ? Я просто не очень понимаю алгоритм действий. Т.е. как задать свой собственный алгоритм определения попадает ли точка в фигуру ? Я переопределил метод contains но при клике он даже не был вызван.. Странно |
|||
|
||||
| math64 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 23 Всего: 72 |
Обычно в своем GraphicsItem нужно переопредить одновременно следующие методы:
и они должны работать согласованно paint() рисует внутри shape(), и соблюдаются соотнношения: boundingRect() = shape().boundingRect() contains() = shape().contains() т.о. для определения принадлежности точки может быть вызвано не contains(), а shape().contains() |
|||
|
||||
| Glad |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 27 Регистрация: 16.8.2005 Репутация: нет Всего: нет |
Спасибо! Ясно примерно. Хотя я так посмотрел.. У QGraphicsItem есть метод shape. Получается что так или иначе возращается QPainterPath(кстати по значению, что тоже смутило учитывая частоту вызова данной функции). Т.е. с помощью shape() мы можем построить свой контур и Qt сожет определить попали ли мы в этот контур автоматически, я правильно понимаю ? Пока конечно не вдаюсь в детали, но с первого взгляда это кажется сложным.. Не проще было бы дать юзеру определять с помощью того же метода contains содержится ли точка в фигуре или нет ? |
|||
|
||||
| math64 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 23 Всего: 72 |
contains() для точки частная задача. по умочанию она вызывает shape().contains()
Если можно выполнить contains() быстрее, можно предложить другую реализацию. shape() нужен для других задач, например фигуры выделение контуром, которое с помощью contains() не сделаешь. shape() возвращает QPainterPath по значению, а не по ссылке, т.к. путь нельзя модиффицировать (если он хранится постоянно), или он может создаваться каждый раз при вызове, чтобы не тратить много памяти на его хранение. Как бы то ни было, конструктор копирования выполняется быстро, т.к. данные хранятся в QPainterPathPrivate, а копия использует те же данные, что и оригинал (в QPainterPathPrivate есть счетчик использования) - так устроены многие классы Qt. |
|||
|
||||
| Glad |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 27 Регистрация: 16.8.2005 Репутация: нет Всего: нет |
А прикол хотите ?
|
|||
|
||||
| math64 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 23 Всего: 72 |
||||
|
||||
| Glad |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 27 Регистрация: 16.8.2005 Репутация: нет Всего: нет |
math64,
Спасибо за ответы! |
|||
|
||||
![]()
|
| Правила форума "С/С++: Кроссплатформенное программирование, 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. |