Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
388 views
in Technique[技术] by (71.8m points)

c++ - 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
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.9k users

...