Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt - Determine absolute widget and cursor position

Tags:

c++

qt

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 } 
like image 596
Dave McClelland Avatar asked Dec 15 '10 13:12

Dave McClelland


People also ask

How do I get the cursor position in Qt?

To set or get the position of the mouse cursor use the static methods QCursor::pos() and QCursor::setPos().

How do you set absolute position of widgets in Qt?

You can use Move function of your widget with two parameters i.e. x and y coordinates. You can also use setGeometry function of your widget with four parameters. In setGeometry function, 1st and 2nd parameters are x and y coordinates respectively and 3rd and 4th parameters are width and height of your widget.

What is Qt widgets?

Widgets are the primary elements for creating user interfaces in Qt. Widgets can display data and status information, receive user input, and provide a container for other widgets that should be grouped together. A widget that is not embedded in a parent widget is called a window.


1 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 */ }
like image 117
Elrohir Avatar answered Sep 25 '22 22:09

Elrohir