4

我目前正在开发图像查看器应用程序。在这个应用程序中,我有一个所谓的“平移缩放”功能。这意味着,当按住某个鼠标按钮时,用户可以通过前后平移来缩放图像。

它工作正常,但随着使用该功能,鼠标(自然)在屏幕上上下移动,并在某个点到达屏幕边界,这将使其停止。相反,我想要一种鼠标保持静止并且只有图像放大率发生变化的行为。

我试图通过调用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

4

3 回答 3

1

我会有一个标志来禁用该事件,默认情况下将是 false。

在事件内部检查 flag 是否为 false,然后执行缩放操作,将 flag 设置为 true 并重置光标。

然后将再次调用该事件并且标志将为真,因此您将标志设置为假,您将准备好处理下一个事件。

您只需确保在从 setCursor 调用接收事件之前,您没有两次或多次调用从实际鼠标触发的鼠标事件。

于 2015-11-11T14:48:37.237 回答
1

假设您没有调用基类mouseMoveEvent,您应该接受该事件以将其标记为正在处理。默认情况下,当您重新实现事件时,它们会被接受,但更明确的是更清楚。打电话e->accept( )

还建议如果您处理任何鼠标事件,则应处理 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拨打电话,当光标在小部件之外时,它仍会收到移动事件,同时按住鼠标按钮。

但是,在缩放时隐藏光标可能是更好的用户体验。

于 2015-11-11T15:13:38.633 回答
0

不要在鼠标事件中使用 event->pos(),使用 QCursor::pos() intead 并检查它是否改变。像这样:

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;
}
于 2020-03-05T11:17:44.803 回答