Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: elive от Март 24, 2010, 09:32



Название: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: elive от Март 24, 2010, 09:32
 Приветствую. Возникла следующая проблема. У меня имеется класс, наследованный от QGraphicsView, к которому я прикрутил рисование мышкой, то есть перегрузил paintEvent. Так же мне необходимо в данный класс добавить сцену, содержащие айтемы. Но после перегрузки, элементы сцены не отображаются, отображается лишь то, что я рисую в QGraphicsView.

Исходная задача у меня такая: при нажатии на айтем, мне необходимо производить рисование. Если рисовать в самом айтеме, то необходимо создавать boundingRect, размером со всю сцену, производительность при этом сильно просидает. Поэтому хочу передавать рисование в QGraphicsView.


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: alexman от Март 24, 2010, 09:40
А если рассмотреть линию, которую ресуешь, как item?


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: elive от Март 24, 2010, 09:57
А если рассмотреть линию, которую ресуешь, как item?
Во втором абзаце я написал, что при таком раскладе сильно падает производительность. + Рисую не обязательно линию, может быть любая траектория.
 Хотя если предложишь, как это реализовать, например через path, чтобы рисовать произвольную траекторию в реальном времени, не нажимая каждый раз кнопку мыши, буду рад и такому варианту :)


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: alexman от Март 24, 2010, 10:09
А если рассмотреть линию, которую ресуешь, как item?
Во втором абзаце я написал, что при таком раскладе сильно падает производительность. + Рисую не обязательно линию, может быть любая траектория.
 Хотя если предложишь, как это реализовать, например через path, чтобы рисовать произвольную траекторию в реальном времени, не нажимая каждый раз кнопку мыши, буду рад и такому варианту :)
Сорри! Не дочитал до конца...


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: GreatSnake от Март 24, 2010, 11:34
Перегружая QGraphicsView::paintEvent() без вызова оригинального paintEvent() вы просто не дали возможность отрисовывть QGraphicsItems.
Для ваших целей лучше подойдёт следующее:
Код
C++ (Qt)
void YourGraphicsView::drawForeground( QPainter* painter, const QRectF& rect )
{
   QGraphicsView::drawForeground( painter, rect );
 
   if( yourDrawRect.intersects( rect ) )   // your mouse painting
     ...
}
 
Но не мешало бы более конкретизировать задачу ...


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: elive от Март 24, 2010, 13:01
Перегружая QGraphicsView::paintEvent() без вызова оригинального paintEvent() вы просто не дали возможность отрисовывть QGraphicsItems.
Для ваших целей лучше подойдёт следующее:
Код
C++ (Qt)
void YourGraphicsView::drawForeground( QPainter* painter, const QRectF& rect )
{
   QGraphicsView::drawForeground( painter, rect );
 
   if( yourDrawRect.intersects( rect ) )   // your mouse painting
     ...
}
 
Но не мешало бы более конкретизировать задачу ...

Спасибо, помогло. Теперь думаю как при нажатии на айтем передавать рисование в QGraphicsView...


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: ufna от Март 24, 2010, 13:05
для вью задай setAcceptChildEvents(true)


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: GreatSnake от Март 24, 2010, 13:11
Цитировать
для вью задай setAcceptChildEvents(true)
Это в какой версии Qt такое есть?

Цитировать
Теперь думаю как при нажатии на айтем передавать рисование в QGraphicsView...
item->update()


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: elive от Март 24, 2010, 13:44
item->update()

 Мне надо, чтобы кликая по области сцены, рисование не происходило. А при нажатии на айтем (mousePress), рисование проходило уже во View. Если в айтеме прописать mousePressEvent, а во View - mouseMoveEvent, то рисование идёт в любом случае, просто линия получается непрерывная. Думаю надо как-то по-заковырестее организовывать, может быть ловить все события и сигналами слать во View (drawForeground)? В физическом смысле, мне нужно при нажатии на объект рисовать его траекторию, по которой он впоследствии будет двигаться.


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: GreatSnake от Март 24, 2010, 14:16
Судя по всему вы выставили у элементов флаг QGraphicsItem::ItemIsSelectable.
Предлагаю его не выставлять, а в YourGraphicsView::mousePressEvent() находить нужный элемент и вызывать его update().


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: elive от Март 24, 2010, 15:15
Судя по всему вы выставили у элементов флаг QGraphicsItem::ItemIsSelectable.
Предлагаю его не выставлять, а в YourGraphicsView::mousePressEvent() находить нужный элемент и вызывать его update().

Не очень понимаю, зачем вызывать update для item'a.
Как я понял, вы предлагаете сравнивать позицию мыши и перебирать позиции всех айтемов, и если они совпадают производить рисование? Попробую так.


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: GreatSnake от Март 24, 2010, 16:44
Цитировать
Не очень понимаю, зачем вызывать update для item'a.
Единственный нормальный способ сказать QGraphicsView-у нарисовать конкретный елемент - это вызвать update() этого элемента.

Цитировать
Как я понял, вы предлагаете сравнивать позицию мыши и перебирать позиции всех айтемов, и если они совпадают производить рисование?
Перебирать необязательно
Код
C++ (Qt)
void YourGraphicsView::mousePressEvent( QMouseEvent* e )
{
     QPoint p( mapToScene( e->pos() ).toPoint() );
     QGraphicsItem* item = itemAt( p );
     if( item )
       item->update();
}
 

PS. Если елементы пересекаются, используйте items().

Хм, я похоже немного не так вас понял.
Ваш случай с YourGraphicsItem::mousePressEvent() по идее должен был делать тоже самое.
Похоже вы просто не так делаете отрисовку в drawForeground().


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: elive от Март 25, 2010, 08:58
Хм, я похоже немного не так вас понял.
Ваш случай с YourGraphicsItem::mousePressEvent() по идее должен был делать тоже самое.
Похоже вы просто не так делаете отрисовку в drawForeground().

Всмысле тоже самое? В drawForeground я только создаю подложку (QImage), рисую по событию mousePressEvent во View, т.к. рисовать в Item более затратно.
Вместо update, как понимаю, буду просто вызывать QPainter и рисовать.


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: GreatSnake от Март 25, 2010, 11:10
Цитировать
В drawForeground я только создаю подложку (QImage)
QGraphicsView отрисовывет сцену в 3 этапа - сначала отрисовывает подложку вызывая drawBackground(), потом отрисовывает сами элементы вызывая paint() этих элементов и уже после этого вызывает drawForeground(), чтобы отрисовать всё что вы пожелаете поверх нарисованной сцены. Так что вы делаете что-то не так и не хотите более подробно объяснить, что реально вы хотите получить на выходе.


Название: Re: Перегрузка QGraphicsView, не отображаются элементы с&
Отправлено: fuCtor от Март 25, 2010, 11:22
Так же узнать item на который кликнули можно используя:
Код
C++ (Qt)
QGraphicsView::mouseMoveEvent(event);
QGraphicsItem * item = scene()->mouseGrabberItem();

Только в этом случае item-ы должны принимать события мыши, иначе будет 0.


Название: Re: Перегрузка QGraphicsView, не отображаются элементы сцены
Отправлено: elive от Март 29, 2010, 13:25
Код
C++ (Qt)
     QPoint p( mapToScene( e->pos() ).toPoint() );
     QGraphicsItem* item = itemAt( p );
 
PS. Если елементы пересекаются, используйте items().

Это работает, если найти точку с точностью до сотых. Попробовал через items(x,y, h, w), вроде работает, если сцену выровнять с координтной системой View. Методом тыка получил setSceneRect(-9, -159, w, h), не знаю почему так.

Так же узнать item на который кликнули можно используя:
Код
C++ (Qt)
QGraphicsView::mouseMoveEvent(event);
QGraphicsItem * item = scene()->mouseGrabberItem();

Только в этом случае item-ы должны принимать события мыши, иначе будет 0.

 Работает, но только 1 раз. Потом данное событие срабатывает в любом случае, куда бы я не кликнул на сцене. То есть, нажимаю на айтем1, выводится информация об айтем1. Потом, куда бы я не кликал, выводится информация айтем1.
 Прописал e->accept(). Не помогает, фокус остаётся на первом айтеме.