用MouseMoveEvent移动无边框QDialog

4 投票
2 回答
3831 浏览
提问于 2025-04-16 16:23

我有一个没有边框的对话框(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

2 个回答

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,因为“遮罩”的无边框窗口比真正的有边框窗口要小一点。我还不知道怎么计算这个差距。

更新。经过很长时间,我发现了一个关键的bug。如果你在应用程序启动后,点击任意按钮的左键,然后把鼠标光标拖离那个按钮,你的应用程序会崩溃,因为我们引用了一个不存在的变量LeftClick。所以在Main类中,我们需要创建LeftClick

2

与其使用 event.pos(),不如试试 event.globalPos()。根据 QMouseEvent 的说明,“如果你因为鼠标事件而移动了这个小部件,使用 globalPos() 返回的全局位置可以避免抖动的情况。”

撰写回答