Qt - Определить абсолютный виджет и позицию курсора
У меня есть QWidget, который содержит несколько детей. Конечная цель - иметь возможность перетаскивать из одного виджета в другой, перемещая что-то между виджетами. Я получил сигнал на контроллер родительского виджета и могу определить, когда перетаскивание начинается и заканчивается правильно. Моя текущая проблема заключается в определении, находится ли мышь над целевым виджетом при наведении мыши вверх.
Я был взволнован, когда увидел underMouse в документах, но он не работает во время событий перетаскивания (когда я тестировал, казалось, он возвращал неправильные значения). В противном случае моей целью было найти прямоугольник, содержащий целевой виджет, и определить, содержит ли он координаты мыши при наведении курсора вверх. Я не могу просто использовать contentRect, так как он возвращает позиции относительно виджета, к которому он вызывается. Я думал, что mapToGlobal даст мне абсолютные значения пикселей экрана, но он также не работает. Я попытался вызвать mapTo в окне родительского виджета, но это также, похоже, не удалось.
Ниже приведен код, показывающий различные QRects и QPoints, которые я получил с помощью различных методов. Может быть, с одним из них произошла простая ошибка, поэтому я предоставил их все.
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 не будет работать для моих целей, так как целевой виджет на самом деле является потомком родительского элемента верхнего уровня.
Обновление Вот код, который в итоге получился. В моем виджете верхнего уровня (который был предком как исходного, так и целевого виджетов) я добавил это:
QRect widgetRect = targetWidget->Geometry();
QPoint mousePos = targetWidget->mapFromGlobal(QCursor::pos());
if(widgetRect.contains(mousePos))
{
// Logic
}
3 ответа
Как уже говорилось, вы должны скорее использовать targetWidget->geometry()
вместо contentsRect()
в этом особом случае.
Далее мне интересно, к какому классу принадлежит код, который вы опубликовали. Метод QWidget::mapToGlobal()
должен вызываться из QWidget, к которому относятся ваши координаты. Если я вас правильно понял, это должно выглядеть примерно так:
QRect widgetRect = targetWidget->geometry();
widgetRect.moveTopLeft(targetWidget->parentWidget()->mapToGlobal(widgetRect.topLeft()));
Затем обратите внимание QCursor::pos()
уже возвращает глобальные экранные координаты, поэтому здесь не нужно ничего отображать:
if (widgetRect.contains(QCursor::pos())) {
/* swap widgets */
}
РЕДАКТИРОВАТЬ: Вероятно, даже лучше не отображать прямоугольник на глобальный, а отображать глобальную позицию курсора на виджет:
if (targetWidget->rect().contains(targetWidget->mapFromGlobal(QCursor::pos()))) {
/* do stuff */
}
Может быть, вы ищете geometry()
или же frameGeometry()
в QWidget. Смотрите здесь для более подробной информации.
Этот метод PyQt вернет True, если позиция мыши находится внутри прямоугольника виджета, включая случаи, когда мышь находится над комбинированным видом внутри виджета
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))