Qt - Determine absolute widget and cursor position

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.

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.

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 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
}

Answers


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

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()));

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

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

EDIT: 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 */
}

Maybe you are looking for geometry() or frameGeometry() in QWidget. See here for more details.


This PyQt method will return True if the mouse position is within the widget's rect - including cases such as the mouse being over a combo view inside the widget

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))

Need Your Help

Drupal: Views: how to group fields

drupal drupal-6

I've created a views of node and I've selected the "fields" option in order to select which fields to display and in which order.

How to perform UPDATE with mysqli->prepare?

php mysqli prepared-statement

As I know there is a way to input data into a mysql database with mysqli, where you do not have to use mysql_real_escape_string. I mean like this: