Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: kamil от Март 01, 2016, 12:22



Название: [РЕШЕНО] Отслеживание передвижений на сцене.
Отправлено: kamil от Март 01, 2016, 12:22
Такая ситуация:
Есть два класса унаследованных от QGraphicsView и QGraphicsItem.

У QGraphicsView переопределен mouseMoveEvent(QMouseEvent* event), для скролла сцены.
Также есть множество QGraphicsItem, некоторые из них можно перемещать (setFlag(QGraphicsItem::ItemIsMovable)).

Проблема в том, что на самом деле из перемещать нельзя, так как mouseMoveEvent у QGraphicsView вызывается как раз когда ты пытаешься перетащить элемент, и перетаскивается вся сцена вместо QGraphicsItem.

Решение, в общем-то ясно - нужно в mouseMoveEvent отслеживать, не началось ли перетаскивание элемента на сцене, и если началось, не двигать сцену. Но как узнать у сцены, что в данный момент активно перетаскивание?

В общем, как-то так:
Цитировать
void MyView::mouseMoveEvent(QMouseEvent* event) {
    static QPoint previousPoint = event->pos();
    if( event->buttons() & Qt::LeftButton /*&& !scene()->isItemsMoves()??? */ ) {
        addOffset( event->pos() - previousPoint );
        updateTransform( scale(), offset() );
    }
    previousPoint = event->pos();
    QGraphicsView::mouseMoveEvent(event);
}

Пока я сделал так, что есть какая-то глобальная переменная, и каждый раз когда происходит клик перемещаемом QGraphicsItem эта переменная ставится в 1, когда отпускает в 0,  и в mouseMoveEvent происходит проверка этой переменной. Но это не самое лучшее решение. Есть какие идеи?


Название: Re: Отслеживание передвижений на сцене.
Отправлено: ssoft от Март 02, 2016, 08:08
Можно сделать, например, так

Код
C++ (Qt)
void MyView::mouseMoveEvent(QMouseEvent* event) {
   QGraphicsView::mouseMoveEvent(event);
   // уже обработано
   if ( event->isAccepted() )
       return;
 
   if( event->buttons() & Qt::LeftButton )
   {
       addOffset( event->pos() - previousPoint );
       updateTransform( scale(), offset() );
   }
   previousPoint = event->pos();
}
 

А в обработчике событий item помечать событие event->accept();


Название: Re: Отслеживание передвижений на сцене.
Отправлено: kamil от Март 03, 2016, 00:16
Можно сделать, например, так

Код
C++ (Qt)
void MyView::mouseMoveEvent(QMouseEvent* event) {
   QGraphicsView::mouseMoveEvent(event);
   // уже обработано
   if ( event->isAccepted() )
       return;
 
   if( event->buttons() & Qt::LeftButton )
   {
       addOffset( event->pos() - previousPoint );
       updateTransform( scale(), offset() );
   }
   previousPoint = event->pos();
}
 

А в обработчике событий item помечать событие event->accept();

Не пошло. Почему-то event всегда event->isAccepted() == false, даже если в mouseMoveEvent у передвигаемых объектов явно вызывать event->accept() перед возвращением. Похоже mouseMoveEvent у QGrahicsScene возвращает not accepted, даже если QGraphicsItem вернул accept.

Может есть еще идеи?


Название: Re: Отслеживание передвижений на сцене.
Отправлено: Igors от Март 03, 2016, 10:34
Пока я сделал так, что есть какая-то глобальная переменная, и каждый раз когда происходит клик перемещаемом QGraphicsItem эта переменная ставится в 1, когда отпускает в 0,  и в mouseMoveEvent происходит проверка этой переменной. Но это не самое лучшее решение. Есть какие идеи?
Не вижу в этом решении ничего плохого. И лучше сделать эти 2 драга явными. Напр юзер нажал и держит пробел - курсор поменялся, ага - это таскать всю сцену. Не нажимал - таскаем айтем(ы)


Название: Re: Отслеживание передвижений на сцене.
Отправлено: kamil от Март 11, 2016, 01:22
Пока я сделал так, что есть какая-то глобальная переменная, и каждый раз когда происходит клик перемещаемом QGraphicsItem эта переменная ставится в 1, когда отпускает в 0,  и в mouseMoveEvent происходит проверка этой переменной. Но это не самое лучшее решение. Есть какие идеи?
Не вижу в этом решении ничего плохого. И лучше сделать эти 2 драга явными. Напр юзер нажал и держит пробел - курсор поменялся, ага - это таскать всю сцену. Не нажимал - таскаем айтем(ы)

Да, похоже решение получше не придумать.