簡體   English   中英

如何使用 Qt 防止 QCursor::setPos() 上的 mouseMoveEvent?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM