web-dev-qa-db-fra.com

Qt - Détermine la position absolue du widget et du curseur

J'ai un QWidget qui contient plusieurs enfants. Le but ultime est de pouvoir glisser-déposer d'un widget à l'autre, en déplaçant quelque chose entre les widgets. Un signal est envoyé au contrôleur de mon widget parent et je peux déterminer quand le glissement commence et se termine correctement. Mon problème actuel consiste à déterminer si la souris est au-dessus du widget cible lorsque vous placez la souris vers le haut.

Je me suis excité quand j'ai vu underMouse dans la documentation, mais cela ne fonctionne pas lors d'événements de glisser-déposer (lorsque j'ai testé, il semblait retourner des valeurs incorrectes). Sinon, mon objectif était de trouver le rectangle contenant le widget cible et de déterminer s'il contenait les coordonnées de la souris sur une souris vers le haut. Je ne peux pas simplement utiliser contentsRect , car il renvoie des positions par rapport au widget sur lequel il est appelé. Je pensais que mapToGlobal me donnerait des valeurs absolues de pixels d’écran, mais il continue également d’échouer. J'ai essayé d'appeler mapTo sur la fenêtre du widget parent, mais cela semblait également échouer.

Le code ci-dessous montre les différents QRects et QPoints que j’ai obtenus avec les différentes méthodes. Peut-être qu'il y a une simple erreur avec l'un d'entre eux, alors je les ai tous fournis.

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 ne fonctionnera pas pour mes besoins, car le widget cible est en réalité parenté par un enfant du parent de niveau supérieur.

Update Voici le code qui a fini par fonctionner. Dans mon widget de niveau supérieur (ancêtre des widgets source et cible), j'ai ajouté ceci:

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

Comme déjà dit, vous devriez plutôt utiliser targetWidget->geometry() au lieu de contentsRect() dans ce cas particulier.

Ensuite, je me demande à quelle classe appartient le code que vous avez posté. La méthode QWidget::mapToGlobal() doit être appelée à partir de QWidget par rapport à laquelle vos coordonnées sont relatives. Si je vous ai bien compris, cela devrait ressembler à quelque chose comme ceci:

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

Ensuite, notez que QCursor::pos() renvoie déjà les coordonnées globales de l’écran, il n’est donc pas nécessaire de mapper quoi que ce soit ici:

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

EDIT: Il est probablement préférable de ne pas mapper le rect sur global, mais de mapper la position du curseur global sur le widget:

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

Peut-être recherchez-vous geometry() ou frameGeometry() dans QWidget. Voir ici pour plus de détails.

2
yasouser

Cette méthode PyQt renverra True si la position de la souris est dans le rect - du widget, y compris des cas tels que la souris survolant une vue combinée inside le 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))
0
flipthefrog