Qt鼠标控制在触摸和非触摸设备上的旋转

Qt Mouse Control of Rotaries on touch and non-touch devices

本文关键字:触摸 旋转 鼠标 控制 Qt      更新时间:2023-10-16

我在Qt中实现了旋转小部件,当用户点击旋转时,鼠标光标被隐藏,鼠标向左/向下拖动旋转逆时针,鼠标向右/向上拖动旋转顺时针。当松开鼠标时,鼠标光标被设置到单击的原始位置。实现如下:

void RotaryWidget::mousePressEvent(QMouseEvent *MouseEvent)
{
    mMousePos = QCursor::pos();
    mPreviousPos = MouseEvent->pos();
    setCursor(Qt::BlankCursor);
}
void RotaryWidget::mouseReleaseEvent(QMouseEvent *MouseEvent)
{
    QCursor::setPos(mMousePos);
    unsetCursor();
}
void RotaryWidget::mouseMoveEvent(QMouseEvent *MouseEvent)
{
    QPoint DeltaPos = MouseEvent->pos() - mPreviousPos;
    // Use DeltaPos to move my rotary
    mPreviousPos = MouseEvent->pos();
}

这样做的好处是,当连续有几个旋转时,用户可以更快地进行调整。

上面的代码有一个bug,如果光标到达屏幕的边缘,鼠标无法移动,所以旋转不会移动。但是,用户看不到光标,所以这是一个问题。我改变了mouseMoveEvent来修复它:

void RotaryWidget::mouseMoveEvent(QMouseEvent *MouseEvent)
{
    if(MouseEvent->globalPos() == mMousePos)
    {
        mPreviousPos = mapFromGlobal(mMousePos);
        return;
    }
    else
    {
        QCursor::setPos(mMousePos);
    }
    QPoint DeltaPos = MouseEvent->pos() - mPreviousPos;
    // Use DeltaPos to move my rotary
    mPreviousPos = MouseEvent->pos();
}

基本上,每次移动鼠标时,都会计算变化,然后将光标设置回原始按下位置(因此它永远不会离开屏幕)。顶部的if确保我们不会一遍又一遍地将鼠标位置设置为原始位置。

这在非触摸屏设备上工作得很好,但在触摸屏设备上,QCursor::setPos()不工作,因为我无法以编程方式设置屏幕上手指的位置!

我没能想出一个满足我所描述的所有需求的解决方案。如果有一种方法可以检测用户是否在使用触摸屏,它可以被修复,但我在Qt中找不到这样的功能。

你可以检查鼠标是在边缘上还是在边缘之外,而不是试图强迫鼠标点击位置,如果是,使用恒定增量增量增量增量(最后移动):

void RotaryWidget::mouseMoveEvent(QMouseEvent *MouseEvent)
{
    QPoint DeltaPos;
    if(!isInsideWindow(MouseEvent))
    {
       DeltaPos = mPrevDeltaPos;
    }
    else
    {
       DeltaPos = MouseEvent->pos() - mPreviousPos;
       mPrevDeltaPos = DeltaPos;
       // Use DeltaPos to move my rotary
       mPreviousPos = MouseEvent->pos();
     }
}
编辑:

另一个选择是基于全局鼠标坐标而不是相对于窗口0的局部坐标来计算DeltaPos——因为只关心两个鼠标坐标之间的差异,所以不需要将位置链接到窗口。在这种情况下,widget将同时适用于触摸和鼠标操作的屏幕-无论光标相对于窗口框架的位置如何,鼠标/手指的相同移动将以相同的方式改变方向。