[英]How to prevent mouseMoveEvent on QCursor::setPos() using Qt?
我目前正在開發一個圖像查看器應用程序。 在這個應用程序中,我有一個所謂的“平移縮放”功能。 這意味着,當按住某個鼠標按鈕時,用戶可以通過前后平移來縮放圖像。
它工作正常,但隨着該功能的使用,鼠標(自然地)在屏幕上上下移動,並在某個時候到達屏幕邊界,這將使其停止。 相反,我想要一種鼠標保持靜止並且只有圖像放大率發生變化的行為。
我試圖通過在QWidget::mouseMoveEvent
調用QCursor::setPos
並在處理完移動后將鼠標重置到初始位置來實現這一點。 只要鼠標幾乎保持靜止(它來回擺動),它就可以工作。 但是,這將導致再次調用鼠標移動事件,從而有效地取消我剛剛所做的調整。 這將導致“擺動”效果。 每次調整都會立即逆轉。
這是截取的代碼,因此您可以了解我在做什么:
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
時防止鼠標移動事件發生?
我將有一個標志來禁用該事件,默認情況下將為 false。
在事件內部檢查標志是否為假,然后執行縮放操作,將標志設置為真並重置光標。
然后該事件將再次被調用並且標志將為真,因此您將標志設置為假,您將准備好處理下一個事件。
在從 setCursor 調用接收事件之前,您只需要確保沒有兩次或多次調用從實際鼠標觸發的鼠標事件。
假設您沒有調用基類mouseMoveEvent
,您應該接受該事件以將其標記為正在處理。 默認情況下,當您重新實現事件時,它們會被接受,但明確表示會更清楚。 調用e->accept( )
。
還建議如果您處理任何鼠標事件,您應該處理所有,鼠標雙擊可能除外。
這是一個保持鼠標靜止的例子,盡管在 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
調用,當光標位於小部件之外時,它仍將接收移動事件,同時按住鼠標按鈕。
但是,在縮放時隱藏光標可能是更好的用戶體驗。
不要在鼠標事件中使用 event->pos(),而是使用 QCursor::pos() 並檢查它是否更改。 像這樣:
void MyWidget::mousePressEvent(QMouseEvent *)
{
mPrevPos=QCursor::pos();
mMoving=false;
}
void MyWidget::mouseMoveEvent(QMouseEvent *)
{
auto cursorPos=QCursor::pos();
if(mPressedPos==cursorPos){
return;
}
if(!mMoving
&& (cursorPos-mPrevPos).manhattanLength()>QApplication::startDragDistance()){
mMoving=true;
}
if(mMoving){
auto diff=cursorPos-mPrevPos;
// move something using diff
QCursor::setPos(mPrevPos);
}
}
void MyWidget::mouseReleaseEvent(QMouseEvent *)
{
mMoving=false;
}
void MyWidget::leaveEvent(QEvent *)
{
mMoving=false;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.