Qt - 确定绝对小部件和光标位置

2021-12-09 00:00:00 qt c++

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

I have a QWidget that contains multiple children. The ultimate goal is to be able to drag and drop from one widget to the other, moving something between widgets. I've got a signal being fired to my parent widget's controller and can determine when the drag is starting and ending correctly. My current problem is determining whether or not the mouse is above the target widget on mouse up.

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

I got excited when I saw underMouse in the docs, but it doesn't work during drag and drop events (when I tested, it seemed to return incorrect values). Failing this, my goal was to find the rectangle containing the target widget and find whether it contained the mouse coordinates on a mouse up. I can't simply use contentsRect, since it returns positions relative to the widget it is being called on. I thought that mapToGlobal would give me absolute screen pixel values, but it keeps failing as well. I tried calling mapTo on the parent widget's window, but that also seemed to fail.

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

Below is code showing the various QRects and QPoints I've gotten with the various methods. Maybe there's a simple error with one of them, so I've provided them all.

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 不适用于我的目的,因为目标小部件是实际上由顶级父级的子级抚养.

mapToParent won't work for my purposes, since the target widget is actually parented by a child of the top-level parent.

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

Update Here's the code that ended up working out. In my top-level widget (that was an ancestor to both the source and target widgets), I added this:

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

推荐答案

正如已经说过的,你应该使用 targetWidget->geometry() 而不是 contentsRect()这个特例.

As already said you should rather use targetWidget->geometry() instead of contentsRect() in this special case.

接下来我想知道您发布的代码属于哪个类.方法 QWidget::mapToGlobal() 应该从您的坐标相对于的 QWidget 调用.如果我猜对了,它应该看起来像这样:

Next I wonder which class the code you posted belongs to. The method QWidget::mapToGlobal() should be invoked from the QWidget your coordinates are relative to. If I got you right, it should look like something like this:

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

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

Then note QCursor::pos() is already returning global screen coordinates, so no need to map anything here:

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

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

Probably it's even better to not map the rect to global, but to map the global cursor position to the widget:

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

相关文章