【问题标题】:Qt - Determine absolute widget and cursor positionQt - 确定绝对小部件和光标位置
【发布时间】:2011-05-25 22:27:22
【问题描述】:

我有一个包含多个孩子的 QWidget。最终目标是能够从一个小部件拖放到另一个小部件,在小部件之间移动某些东西。我有一个信号被触发到我的父小部件的控制器,并且可以确定拖动何时正确开始和结束。我目前的问题是确定鼠标是否在鼠标上的目标小部件上方。

当我在文档中看到underMouse 时,我很兴奋,但它在拖放事件期间不起作用(当我测试时,它似乎返回了不正确的值)。如果做不到这一点,我的目标是找到包含目标小部件的矩形,并找出它是否包含鼠标上的鼠标坐标。我不能简单地使用contentsRect,因为它返回相对于它被调用的小部件的位置。我认为mapToGlobal 会给我绝对的屏幕像素值,但它也一直失败。我尝试在父窗口小部件的窗口上调用 mapTo,但这似乎也失败了。

下面的代码显示了我使用各种方法获得的各种 QRects 和 QPoints。也许其中一个有一个简单的错误,所以我已经全部提供了。

QRect relativeWidgetRect = targetWidget->contentsRect();
QRect *absoluteWidgetRect = new QRect(QWidget::mapToGlobal(relativeWidgetRect.topLeft()), QWidget::mapToGlobal(relativeWidgetRect.bottomRight()));
QRect *widgetRect = new QRect(mapTo(window(), relativeWidgetRect.topLeft()), mapTo(window(), relativeWidgetRect.bottomRight()));
QPoint relativeMousePos = QCursor::pos();
QPoint absoluteMousePos = QWidget::mapToGlobal(relativeMousePos);
QPoint widgetMousePos = mapTo(window(), relativeMousePos);

mapToParent 不适用于我的目的,因为目标小部件实际上是由顶级父级的子级作为父级的。

更新这是最终成功的代码。在我的顶级小部件(它是源小部件和目标小部件的祖先)中,我添加了以下内容:

QRect widgetRect = targetWidget->Geometry();
QPoint mousePos = targetWidget->mapFromGlobal(QCursor::pos());
if(widgetRect.contains(mousePos))
{
// Logic
}

【问题讨论】:

  • 我在您更新的代码 sn-p 中发现了一个错误。 QWidget 的 geometry() 方法返回相对于其父级的坐标,因此在下一行中您应该添加父小部件引用 parentWidget()->:QPoint mousePos = targetWidget->parentWidget()->mapFromGlobal(QCursor::pos());

标签: c++ qt


【解决方案1】:

如前所述,在这种特殊情况下,您应该使用targetWidget->geometry() 而不是contentsRect()

接下来我想知道您发布的代码属于哪个类。 QWidget::mapToGlobal() 方法应该从您的坐标相对的 QWidget 调用。如果我没记错的话,它应该是这样的:

QRect widgetRect = targetWidget->geometry();
widgetRect.moveTopLeft(targetWidget->parentWidget()->mapToGlobal(widgetRect.topLeft()));

那么注意QCursor::pos()已经返回了全局屏幕坐标,所以这里不需要映射任何东西:

if (widgetRect.contains(QCursor::pos())) {
    /* swap widgets */
}

编辑:最好不要将矩形映射到全局,而是将全局光标位置映射到小部件:

if (targetWidget->rect().contains(targetWidget->mapFromGlobal(QCursor::pos()))) {
    /* do stuff */
}

【讨论】:

  • 啊哈,谢谢!我已经用最终解决我的问题的代码更新了我的问题。
【解决方案2】:

也许您正在 QWidget 中寻找 geometry()frameGeometry()。详情请见here

【讨论】:

    【解决方案3】:

    如果鼠标位置在小部件的矩形内,则此 PyQt 方法将返回 True - 包括 情况,例如鼠标在组合视图上 inside 小部件

    def underMouse(self):
        pos = QtGui.QCursor.pos()
        rect = self.rect()
        leftTop     = self.mapToGlobal(QtCore.QPoint(rect.left(),rect.top()))
        rightBottom = self.mapToGlobal(QtCore.QPoint(rect.right(),rect.bottom()))
        globalRect = QtCore.QRect(leftTop.x(), leftTop.y(), rightBottom.x(), rightBottom.y() )
        return globalRect.contains(self.mapToGlobal(pos))
    

    【讨论】: