2015-11-11 6 views
2

В настоящее время я разрабатываю приложение для просмотра изображений. В этом приложении у меня есть так называемая функция панорамирования. Это означает, что, удерживая определенную кнопку мыши, пользователь может масштабировать изображение путем панорамирования вперед и назад.C++/Qt: предотвратить `mouseMoveEvent` на` QCursor :: setPos() `

Он отлично работает, но при использовании функции мышь (естественно) перемещается вверх и вниз по экрану и в какой-то момент достигнет границ экрана, что заставит ее остановиться. Вместо этого мне хотелось бы, чтобы мышь оставалась неподвижной и менялось только увеличение изображения.

Я попытался достичь этого, вызвав QCursor::setPos внутри QWidget::mouseMoveEvent и сбросив мышь в исходное положение после того, как обработал ход. Он работает так далеко, что мышь остается почти неподвижной (она вибрирует вперед и назад). Однако это приведет к тому, что событие перемещения мыши будет вызываться снова, фактически аннулируя только что сделанную настройку. Это приведет к «зависанию» эффекта. Каждая корректировка будет немедленно отменена.

Вот код пропущен, так что вы получите представление о том, что я делаю:

void ImageView::mouseMoveEvent(QMouseEvent *e) { 
    //some code 
    if (_panZooming) { 
     //some code here 

     //doesn't work as expected because it invokes this event again 
     QCursor::setPos(mapToGlobal(_initialMousePosition.toPoint())); 
    } 
} 

Есть ли способ, чтобы предотвратить событие перемещения мыши произойти при использовании QCursor::setPos?

+0

'QCursor :: setPos()' вызовет 'mouseMoveEvent()', причины. Возможно, вы хотите проверить, доходит ли курсор до границы экрана, например, если курсор находится на верхней границе экрана, продолжайте увеличивать/уменьшать масштаб независимо от того, движется курсор или нет. – helsinki

+0

Но как мне получить дельта тогда? Дельта вычисляется разностью координаты y мыши в исходном положении до положения, которое оно в настоящее время находится.Если пользователь продолжает двигаться вверх, но мышь больше не перемещается, потому что она находится на краю экрана, то в y-координате больше не будет никакой разницы. – user1488118

+1

вы можете получить позицию курсора desktopwidget и скрыть фактический курсор для лучшего удобства пользователя и сбросить мышь в положение мыши. –

ответ

1

Предполагая, что вы не вызываете базовый класс mouseMoveEvent, вы должны accept the event отметить его как обрабатываемый. По умолчанию они принимаются, когда вы повторно реализуете событие, но яснее явное. Позвоните по телефону e->accept().

Также рекомендуется, чтобы вы обрабатывали любые события мыши, you should handle all, за исключением, возможно, двойного щелчка мыши.

Вот пример держа мышь еще, хотя на OS X есть случайная вспышка, которая, как представляется, из-за того, как Qt обрабатывают события

class MyWidget : public QWidget 
{ 
    void mousePressEvent(QMouseEvent* e) 
    { 
     m_pos = e->globalPos(); 
     m_lastPos = m_pos; 
     QWidget::mousePressEvent(e); 
    } 

    void mouseMoveEvent(QMouseEvent* e) 
    { 
     // Calculate relative zoom factor 
     // scaled down (/ 10) for image zooming 

     m_zoomFactor += ((float)e->globalPos().y() - m_lastPos.y())/10; 

     QCursor::setPos(m_pos); 
     m_lastPos = m_pos; 
     e->accept(); 

     qDebug() << m_zoomFactor << endl; 
    } 

    void mouseReleaseEvent(QMouseEvent* e) 
    { 
     QWidget::mouseReleaseEvent(e); 
    } 

private: 
    QPoint m_pos; 
    QPoint m_lastPos; 

    float m_zoomFactor = 0; // C++ 11 initialisation 
}; 

Если вы не потрудились при хранении мыши стационарный, выньте вызов QCursor::setPos, и это все равно будет получать события перемещения, когда курсор находится за пределами виджета, в то время как кнопка мыши удерживается нажатой.

Тем не менее, при масштабировании может быть лучше, чем у пользователя hiding the cursor.

+0

Хм .. это ничего не меняет. Я также не понимаю, зачем это нужно. Я имею в виду, что курсор перемещается операционной системой. Моя программа просто реагирует на это событие перемещения. Принятие события не помешает перемещению мыши. – user1488118

+0

Я все же хочу скрыть курсор. Моя проблема также заключается не в том, что мышь не держится, на самом деле это (эта часть работает). Я также знаю, что я все равно буду получать события перемещения мыши, когда я вне виджета. Проблема, которую я хочу предотвратить, - это то, что происходит, когда я достигаю края экрана. Затем мышь больше не будет двигаться, поэтому y-координата положения мыши больше не будет изменяться. Поскольку я вычисляю масштаб-дельту в событии перемещения мыши из этой самой координаты y, никакого дальнейшего увеличения не произойдет, потому что координата y остается неизменной. – user1488118

+0

Теперь я попытался обойти это, сбросив мышь в исходное положение после каждого события перемещения. Однако это обрабатывается так, как если бы пользователь переместил мышь назад и запускал новое событие перемещения мыши, фактически аннулируя последний ход. Это то, что я должен как-то предотвратить. – user1488118

1

У меня был бы флаг для отключения события с по умолчанию будет ложным.

внутри проверки события, если флаг является ложным, затем выполнить операцию масштабирования, установить флаг в true и сбросить курсор.

, то событие будет вызвано снова, и флаг будет истинным, поэтому вы установите флаг на false, и вы будете готовы обработать следующее событие.

Вам нужно только удостовериться, что у вас нет двух или более вызовов при запуске мыши с фактической мыши перед получением события из вызова setCursor.

+0

Возможно, это сработает, но каким-то образом я хотел бы, чтобы решение было немного больше ... «опрятным». Таким образом, я просто могу пропустить другие события перемещения мыши. – user1488118