Qt:坐标/鼠标/触摸

鼠标坐标

1. 窗口坐标( 相对于窗口)
Qpoint QMouseEvent::pos(); 或 x() 或 y()
2. 全局坐标( 相对于屏幕)
Qpoint QMouseEvent::globPos(); 或 screenPos();
int x = cursor().pos().x(); 或 globalX(); 
int y = cursor().pos().y(); 或 globalY(); 
3. 窗口坐标转全局坐标
mapToGlobal()
4. 全局坐标转窗口坐标
mapFromGlobal()

控件坐标

控件相对于父窗口的坐标:QPointQWidget::pos()

鼠标事件

1. 按下
void mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)  // 左键按下
    {
    }
	}
2. 移动
自动触发:setMouseTracking(true); 
void mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton)
    { 
    }
}
3. 释放
void mouseReleaseEvent(QMouseEvent *event)
{
}
4. 双击
void mouseDoubleClickEvent(QMouseEvent *event)
{
}
5. 滚轮
void wheelEvent(QWheelEvent *event)
{
    if(event->delta() > 0)// 当滚轮远离使用者时
    {
    }
    else//当滚轮向使用者方向旋转时
    {
    }
}

触摸事件
设置窗口属性:setAttribute(Qt::WA_AcceptTouchEvents); // 窗口接受触摸事件
相对于窗口的位置:TouchPoint::pos()/lastPos()/lastScreenPos()
区域:TouchPoint::rect();

bool event(QEvent * event)
{
    switch (event->type())
    {
        case QEvent::TouchBegin: // 手指与触摸屏开始接触时
        {
            break;
        }
        case QEvent::TouchUpdate: // 手指与触摸屏接触过程中
        {
            break;
        }
        case QEvent::TouchEnd: // 手指离开触摸屏
        {
            QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
            QList<QTouchEvent::TouchPoint> tpList = touchEvent->touchPoints(); // 触控点
            for (int i = 0; i < tpList.size(); i++)
            {
                QTouchEvent::TouchPoint tp = tpList.at(i); // event里的数值在touchPoints里
                tp.lastPos();
            }
            event->accept();
            break;
        }
        default: break;
    }
    return QWidget::event(event);
}

焦点

当前窗口:QApplication::activeWindow()
当前窗口内的控件:QApplication::focusWidget()

QWidget *currentitem=QApplication::focusWidget();
if((currentitem!=NULL)&&(currentitem->inherits("QLineEdit"))) // 是否是某个类的实例
{
    QLineEdit *p=qobject_cast<QLineEdit *>(currentitem);
}
<think>我们正在处理用户关于Qt6中QWheelEvent构造函数变更的问题。用户引用了一段代码,展示了Qt5和Qt6在模拟滚轮事件时的差异。我们需要解释如何将Qt5中的QWheelEvent构造转换为Qt6的版本。 根据引用[1]: ``` //模拟鼠标滚轮 #if (QT_VERSION < QT_VERSION_CHECK(6,0,0)) QWheelEvent wheelEvent(QPoint(0, 0), -scal, Qt::LeftButton, Qt::NoModifier); #else QWheelEvent wheelEvent(QPointF(0, 0), QPointF(0, 0), QPoint(0, 0), QPoint(0, -scal), Qt::LeftButton, Qt::NoModifier, Qt::ScrollBegin, false); #endif ``` 在Qt5中,构造函数参数为: - pos: 事件的位置(QPoint) - delta: 滚轮滚动的距离(这里用-scal表示) - buttons: 按下的鼠标按钮(这里是左键) - modifiers: 键盘修饰符(无) 在Qt6中,QWheelEvent的构造函数发生了较大变化。新的构造函数需要更多的参数: 1. `position`: 事件的位置,使用QPointF(浮点坐标) 2. `globalPosition`: 全局位置,使用QPointF(浮点坐标) 3. `pixelDelta`: 以像素为单位的滚动量(QPoint) 4. `angleDelta`: 以角度为单位的滚动量(QPoint),这里我们传递了(0, -scal),表示垂直滚动 5. `buttons`: 按下的鼠标按钮(左键) 6. `modifiers`: 键盘修饰符(无) 7. `phase`: 滚动阶段(这里设置为Qt::ScrollBegin表示滚动开始) 8. `inverted`: 是否反转(false表示不反转) 因此,用户需要将Qt5的构造转换为Qt6的上述形式。注意,在Qt6中,我们通常使用angleDelta来模拟滚轮滚动的角度变化,而pixelDelta用于高精度设备(如触摸板)。在模拟传统鼠标滚轮时,我们主要设置angleDelta。 另外,引用[2]提到了Qt6的高分屏支持,这可能会影响坐标计算。但用户当前的问题集中在事件构造上,所以我们先专注于事件构造。 现在,我们给出一个通用的转换方法: ### Qt5 到 Qt6 的QWheelEvent构造转换 在Qt5中,模拟滚轮事件的构造如下: ```cpp QWheelEvent wheelEvent(QPoint(0, 0), delta, buttons, modifiers); ``` 在Qt6中,应转换为: ```cpp QWheelEvent wheelEvent( QPointF(0, 0), // 局部位置,QPointF类型 QPointF(0, 0), // 全局位置,QPointF类型 QPoint(), // pixelDelta,如果没有则设为QPoint(0,0) QPoint(0, delta), // angleDelta,这里垂直滚动,所以y设为delta(正值表示向上滚动,负值向下) buttons, // 鼠标按钮 modifiers, // 键盘修饰符 Qt::ScrollBegin, // 滚动阶段,模拟一次滚动开始 false // 是否反转 ); ``` 注意:在Qt6中,我们通常需要指定滚动阶段(phase)。如果只是模拟一次滚轮滚动,使用`Qt::ScrollBegin`或`Qt::NoScrollPhase`都可以,但为了模拟一次完整的滚动,建议使用`Qt::ScrollBegin`,然后紧接着再发送一个`Qt::ScrollEnd`?但是,根据引用[1]中的示例,它只发送了一个事件,并且使用了`Qt::ScrollBegin`。实际上,对于大多数控件来说,只需要一个事件即可。如果需要平滑滚动,则需要多个事件(更新阶段)。 ### 代码示例 假设我们要模拟一次向下滚动(通常向下滚动是负值),滚动量为120(这是传统鼠标滚轮一次滚动的典型角度增量,相当于15度,因为120/8=15度)。在Qt5中,我们可能这样写: ```cpp int delta = -120; // 向下滚动 QWheelEvent wheelEvent(QPoint(0,0), delta, Qt::LeftButton, Qt::NoModifier); ``` 在Qt6中,则这样写: ```cpp int delta = -120; QWheelEvent wheelEvent( QPointF(0, 0), QPointF(0, 0), QPoint(0,0), QPoint(0, delta), // 注意:这里y分量设置为负值,表示向下滚动 Qt::LeftButton, Qt::NoModifier, Qt::ScrollBegin, false ); ``` ### 注意事项 1. **坐标系统**:在Qt6中,位置使用QPointF,因此需要传递浮点数坐标。如果使用整数坐标点,可以隐式转换或者显式构造为QPointF。 2. **滚动方向**:在QWheelEvent中,angleDelta的y正值表示向上滚动(远离用户),负值表示向下滚动(靠近用户)。这与Qt5中的delta符号约定相同。 3. **滚动阶段**:在模拟时,如果只是简单的一次滚动,使用`Qt::ScrollBegin`即可。如果是连续的滚动(如触控板),则需要发送多个事件并设置`Qt::ScrollUpdate`,最后以`Qt::ScrollEnd`结束。 4. **高分屏适配**:如果程序需要在高分屏上运行,注意坐标转换(引用[2]中提到)。但在模拟事件时,我们传入的是局部坐标和全局坐标,这些坐标应该是逻辑坐标Qt会自动根据缩放因子转换。如果程序内部有坐标计算,可能需要考虑缩放因子,但事件模拟本身不需要额外处理。 ### 相关问题生成 根据用户的问题,我们生成以下相关问题: 1. 在Qt6中,如何模拟连续的滚轮事件(包括开始、更新和结束阶段)? 2. 如何处理高分屏下的滚轮事件坐标转换? 3. 在Qt6中,QWheelEvent的pixelDelta和angleDelta有什么区别? 4. 如何为自定义控件处理滚轮事件以实现平滑滚动? ### 回答用户 综上所述,用户询问的Qt5代码: ```cpp QWheelEvent wheelEvent(QPoint(0, 0), -scal, Qt::LeftButton, Qt::NoModifier); ``` 在Qt6中应修改为: ```cpp QWheelEvent wheelEvent(QPointF(0, 0), QPointF(0, 0), QPoint(0, 0), QPoint(0, -scal), Qt::LeftButton, Qt::NoModifier, Qt::ScrollBegin, false); ``` 这里,`scal`表示滚动的角度增量(与Qt5相同),负号表示向下滚动[^1]。 </think>### Qt6 中 `QWheelEvent` 构造函数的修改方法 在 Qt6 中,`QWheelEvent` 的构造函数发生了重大改变。您提到的 Qt5 代码: ```cpp QWheelEvent wheelEvent(QPoint(0, 0), -scal, Qt::LeftButton, Qt::NoModifier); ``` 在 Qt6 中应修改为: ```cpp QWheelEvent wheelEvent( QPointF(0, 0), // 局部位置 (QPointF) QPointF(0, 0), // 全局位置 (QPointF) QPoint(0, 0), // 像素滚动量 (pixelDelta) QPoint(0, -scal), // 角度滚动量 (angleDelta) Qt::LeftButton, // 鼠标按键 Qt::NoModifier, // 键盘修饰符 Qt::ScrollBegin, // 滚动阶段[^1] false // 是否反转方向 ); ``` #### 关键参数解析: | 参数 | 类型 | 说明 | Qt6 变化 | |------|------|------|----------| | **position** | `QPointF` | 鼠标在接收组件内的位置 | Qt5 用 `QPoint`,Qt6 改为 `QPointF` | | **globalPosition** | `QPointF` | 鼠标在屏幕上的全局位置 | Qt5 用 `QPoint`,Qt6 改为 `QPointF` | | **pixelDelta** | `QPoint` | 像素级滚动量(触控板手势) | 新增参数 | | **angleDelta** | `QPoint` | 角度滚动量(传统鼠标滚轮) | 替代 Qt5 的单个 `delta` 值 | | **phase** | `Qt::ScrollPhase` | 滚动阶段(开始/更新/结束) | 新增参数,支持连续手势 | #### 实际应用场景示例 模拟向下滚轮滚动(滚动量为 `scal`): ```cpp // Qt5 实现 QWheelEvent wheelEvent(QPoint(0, 0), -scal, Qt::LeftButton, Qt::NoModifier); // Qt6 等效实现 QWheelEvent wheelEvent( QPointF(0, 0), QPointF(0, 0), QPoint(0, 0), // pixelDelta 设为0 (传统鼠标) QPoint(0, -scal), // angleDelta.y() 代表垂直滚动 Qt::LeftButton, Qt::NoModifier, Qt::ScrollBegin, // 单次滚动视为开始阶段 false ); ``` #### 高分屏适配建议 在 Qt6 中创建事件时需注意坐标精度: ```cpp // 获取设备像素比 (解决高分屏模糊问题)[^2] qreal dpr = devicePixelRatio(); // 构造时使用缩放后的坐标 QWheelEvent wheelEvent( QPointF(10 * dpr, 20 * dpr), // 局部位置 QPointF(100 * dpr, 200 * dpr),// 全局位置 ... // 其他参数 ); ``` #### 完整事件模拟流程 ```cpp // 创建一个向下滚动120角度单位的滚轮事件 int scal = 120; // 传统鼠标一次滚动的标准值 #if (QT_VERSION < QT_VERSION_CHECK(6,0,0)) QWheelEvent event(QPoint(0, 0), -scal, Qt::LeftButton, Qt::NoModifier); #else QWheelEvent event( QPointF(0, 0), QPointF(0, 0), QPoint(0, 0), // 传统滚轮无像素增量 QPoint(0, -scal), // 角度增量(负值=向下) Qt::LeftButton, Qt::NoModifier, Qt::ScrollBegin, false ); #endif // 发送事件到目标组件 QApplication::sendEvent(targetWidget, &event); ``` > **重要提示**:Qt6 废弃了 `QWheelEvent::delta()`,统一使用 `angleDelta().y()` 获取垂直滚动量[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值