Перемещение безрамочного QDialog с помощью mouseMoveEvent

#python #pyqt #mouseevent #qdialog

#python #pyqt #mouseevent #qdialog

Вопрос:

Итак, у меня есть безрамочный QDialog, который я хочу иметь возможность перемещать, просто щелкая и перетаскивая его. Учитывая приведенный ниже код, перетаскивание диалогового окна всегда привязывает самый верхний левый угол (0,0) диалогового окна к мыши. Как я могу обойти это, или, скорее, какова может быть математика для этого?

Стандартный QDialog со следующим базовым подклассом:

 class Main(QtGui.QDialog):
    def __init__(self, args):
        QtGui.QDialog.__init__(self)

    def mouseMoveEvent(self, event):
        super(Main, self).mouseMoveEvent(event)
        if self.leftClick == True: self.moveWindow(event.globalPos())

    def mousePressEvent(self, event):
        super(Main, self).mousePressEvent(event)
        if event.button() == QtCore.Qt.LeftButton:
            self.leftClick = True

    def mouseReleaseEvent(self, event):
        super(Main, self).mouseReleaseEvent(event)
        self.leftClick = False
  

Ответ №1:

Вместо event.pos() попробуйте вызвать event.globalPos(). Из ссылки на QMouseEvent: «Если вы перемещаете виджет в результате события мыши, используйте глобальную позицию, возвращаемую globalPos(), чтобы избежать тряски».

Комментарии:

1. Отлично! Это сработало, я обновил свой приведенный выше код, чтобы показать, где я нахожусь на данный момент. Теперь мне нужно иметь возможность удерживать мышь там, где она находится по отношению к диалоговому окну, поскольку всякий раз, когда я щелкаю левой кнопкой мыши, чтобы перетащить диалоговое окно, верхний левый угол диалогового окна привязывается к мыши.

2. вы решили эту проблему? моя мышь также перемещается в верхний левый угол диалогового окна.. я не могу от этого избавиться

3. Нет, я еще этого не делал, я просто разобрался с его зависанием на данный момент. Надеюсь, кто-нибудь сможет прийти и помочь.

4. Привет, я столкнулся с той же проблемой и решил ее. Сохраните координаты первого щелчка в mousePressEvent: self.clickX = event.x() self.clickY = event.y() Затем переместите окно с поправкой на первоначальное местоположение щелчка: self.move(event.globalPos(event.globalX-self.clickX, event.globalY-self.clickY)

Ответ №2:

Предлагаемое решение перемещает окно, но курсор мыши перемещается на 0,0 окна. Я хотел, чтобы курсор мыши все время оставался на x, y окна.

Вот обновленная версия кода [в QT5]:

 X=0
X2=8  #!!!!
Y=0
Y2=30 #!!!!
class Main(QtWidgets.QMainWindow):
    leftClick = False #! IMPORTANT

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

    def mouseMoveEvent(self, event):
        super(Main, self).mouseMoveEvent(event)
        if self.leftClick == True: 
            self.move(event.globalPos().x()-X-X2,event.globalPos().y()-Y-Y2)

    def mousePressEvent(self, event):
        super(Main, self).mousePressEvent(event)
        if event.button() == QtCore.Qt.LeftButton:
            self.leftClick = True
            global X,Y
            X=event.pos().x()
            Y=event.pos().y()

    def mouseReleaseEvent(self, event):
        super(Main, self).mouseReleaseEvent(event)
        self.leftClick = False
  

Для безрамочного окна (созданного с помощью window.setMask() ) мне нужны некоторые константы, такие как X2 и Y2, потому что «замаскированное» безрамочное окно немного меньше реального оформленного окна. Пока не знаю, как вычислить эту разницу.

ВВЕРХ.Спустя долгое время я обнаружил одну критическую ошибку. Если вы нажмете левую кнопку мыши на любой кнопке (сразу после запуска приложения) и отведете курсор мыши от этой кнопки, ваше приложение завершит работу, потому что мы ссылаемся на несуществующую переменную LeftClick. Вот почему в классе Main нам нужно создать LeftClick.