| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > QGraphicsPathItem vs QVector<QGraphicsLineItem> |
| Автор: Glad 23.4.2014, 12:26 |
| Доброго времени суток! У меня задача нарисовать дорогу по модели(данные). Я нашёл(случайно) класс QGraphicsPathItem и все связанные с ним(QPainterPath, например). Но взглянув внутрь, как-то смутился.. Черепашья графика ? Зачем нужен этот класс ? И имеет ли он какие-нибудь преимущества над скажем QVector<QGraphicsLineItem> ? Заранее благодарю. |
| Автор: Amp 23.4.2014, 13:15 |
| QPainterPath позволяет создавать сложные контуры и кривые, комбинируя их из простых линий, дуг, кривых Безье, тестовых глифов и т.п. Полученный путь (path) можно сохранить и использовать (отрисовать) в будущем. Стандартная сущность для векторной графики (аналог, например, cairo_path_t в cairo). Все это конечно же можно аппроксимировать вручную линиями, сложив их в вектор, но это мартышкин труд с кучей недостатков. Например будут проблемы с заливкой, пересечениями контуров, соединениями между линиями (joins). |
| Автор: Glad 23.4.2014, 14:28 |
| Вы знаете меня смутило несколько вещей в этом всём деле. Вот несколько из них: * Каждый элемент Path это не обязательно фигура.. В частности, там возвращается тип объекта moveTo, что как-то странно(хотя в терминах черепашьей графики это нормально). * Селекшн не всегда работает правильно.. Я нарисовал тестовую ломанную с помощью этих инструментов и ломанная выделялась даже если я кликал мимо нее. Впрочем, определить алгоритм попадания я так и не смог: по началу я подумал что это просто попадание в BoundingBox ломанной, но потом потестировав и "потыкав" по экрану, понял что это не так. * Нет возможности выделять и редактировать элементы ломаной. Если я захочу выделить элемент ломаной и что-то с ним сделать(например, изменить толщину дороги в этом участке или сменить тип дороги с гравейки на асфальт) то этого не сделаешь с помощью этих инструментов(а может быть я их просто не знаю?). Вот как-то так.. Всё конечно зависит от решаемой задачи.. Если задача вывести буквы/цифры без возможности редактирования, то наверное этот инструмент подошёл как нельзя лучше. |
| Автор: math64 24.4.2014, 07:38 |
| Это не черепашья графика. Черепашья графика - это когда изображение непросредственно выводится на монитор, что медленно и происходит мерцание экрана. В Qt обязательная двойная буферизация, как что мерцания не будет. moveTo и lineTo - естественный способ задания кривой. В итоге это сводится к аналогичным вызовам Microsoft API. QPainterPath задает одну область, заливаемую одной кистью (хотя возможно, градиентной или пустой) и обводимой одним пером (хотя возможно, градиентным или пустым). Если нужно что-то выделить другим цветом, нужен второй QPainterPath. QPainterPath следует рассматривать как черный ящик. Хотя можно получить точки moveTo и lineTo, лучше их хранить где-то в своём классе. Выделение действительно, иногда ведёт себя не так, как хочется. В этом случае нужно писать своё выделение. |
| Автор: Glad 24.4.2014, 12:50 | ||
А как это сделать ? Я просто не очень понимаю алгоритм действий. Т.е. как задать свой собственный алгоритм определения попадает ли точка в фигуру ? Я переопределил метод contains но при клике он даже не был вызван.. Странно |
| Автор: math64 24.4.2014, 15:01 | ||
Обычно в своем GraphicsItem нужно переопредить одновременно следующие методы:
и они должны работать согласованно paint() рисует внутри shape(), и соблюдаются соотнношения: boundingRect() = shape().boundingRect() contains() = shape().contains() т.о. для определения принадлежности точки может быть вызвано не contains(), а shape().contains() |
| Автор: Glad 24.4.2014, 23:45 | ||
Спасибо! Ясно примерно. Хотя я так посмотрел.. У QGraphicsItem есть метод shape. Получается что так или иначе возращается QPainterPath(кстати по значению, что тоже смутило учитывая частоту вызова данной функции). Т.е. с помощью shape() мы можем построить свой контур и Qt сожет определить попали ли мы в этот контур автоматически, я правильно понимаю ? Пока конечно не вдаюсь в детали, но с первого взгляда это кажется сложным.. Не проще было бы дать юзеру определять с помощью того же метода contains содержится ли точка в фигуре или нет ? |
| Автор: math64 25.4.2014, 07:24 |
| contains() для точки частная задача. по умочанию она вызывает shape().contains() Если можно выполнить contains() быстрее, можно предложить другую реализацию. shape() нужен для других задач, например фигуры выделение контуром, которое с помощью contains() не сделаешь. shape() возвращает QPainterPath по значению, а не по ссылке, т.к. путь нельзя модиффицировать (если он хранится постоянно), или он может создаваться каждый раз при вызове, чтобы не тратить много памяти на его хранение. Как бы то ни было, конструктор копирования выполняется быстро, т.к. данные хранятся в QPainterPathPrivate, а копия использует те же данные, что и оригинал (в QPainterPathPrivate есть счетчик использования) - так устроены многие классы Qt. |
| Автор: Glad 25.4.2014, 18:53 |
| А прикол хотите ? |
| Автор: math64 25.4.2014, 22:33 | ||
Именно так. при прорисовке нужно смотреть на параметр option |
| Автор: Glad 26.4.2014, 14:00 |
| math64, Спасибо за ответы! |