在 Qt 中使用鼠标中键单击和拖动移动整个窗口

Posted

技术标签:

【中文标题】在 Qt 中使用鼠标中键单击和拖动移动整个窗口【英文标题】:Move entire window with Middle Mouse Click & Drag in Qt 【发布时间】:2020-07-06 04:08:43 【问题描述】:

我有一个包含许多子小部件的 Qt 程序。我希望用户能够通过鼠标中键单击并拖动来移动窗口,当没有孩子时它可以正常工作,如下所示:

class MainWindow(QtGui.QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.startPos = QtCore.QPoint()

    def mousePressEvent(self, event):
        self.startPos = event.pos()
        super(MainWindow, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() == QtCore.Qt.MiddleButton:
            delta = event.pos() - self.startPos
            self.move(self.pos() + delta)
            event.accept()
        super(MainWindow, self).mouseMoveEvent(event)

但是当我用所有子小部件及其子小部件等填充我的小部件时。如果我单击边距/填充区域,我只会捕获事件,而不是小部件中的其他任何地方。

有没有办法让鼠标中键拖动事件在途中可以与子小部件一起使用?

【问题讨论】:

【参考方案1】:

当鼠标事件被与其相关的小部件截获时,它们会被自动接受并且不会被中继到父小部件。虽然大多数小部件会忽略中间点击,但有些实际上会忽略,因此您的主窗口永远不会收到它们。

解决方案是在 QApplication 上安装一个事件过滤器,以便您感兴趣的任何鼠标事件在发送到任何可能的目标小部件之前都会被过滤:

class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        # just some test widgets
        layout = QtWidgets.QGridLayout(self)
        for row in range(4):
            for col in range(4):
                layout.addWidget(QtWidgets.QPushButton('Button'), row, col)
        layout.addWidget(QtWidgets.QTextEdit(), 
            layout.rowCount(), 0, 1, layout.columnCount())

        self.startPos = None
        # install the event filter on the application
        QtWidgets.QApplication.instance().installEventFilter(self)

    def eventFilter(self, source, event):
        if (event.type() == QtCore.QEvent.MouseButtonPress and 
            event.button() == QtCore.Qt.MiddleButton):
                self.startPos = event.pos()
                return True
        elif event.type() == QtCore.QEvent.MouseMove and self.startPos is not None:
            self.move(self.pos() + event.pos() - self.startPos)
            return True
        elif event.type() == QtCore.QEvent.MouseButtonRelease and self.startPos is not None:
            self.startPos = None
            return True
        return super(MainWindow, self).eventFilter(source, event)

【讨论】:

像魅力一样工作!一个问题,既然我安装了这个事件过滤器,我应该删除主窗口上的mouseMoveEventmousePressEvent 实现,对吧? @MohammedHamid 是的,它们是不必要的。 这可以得到中间点击,但现在我所有的按钮都不起作用,如何解决这个问题 @ChopLabalagun 谢谢,已修复,请参阅更新。 是的,我做了那个改变,在问这个问题之前,这个方法工作正常,但是当我点击应用程序上的一个按钮时,这个按钮不再做任何事情了。

以上是关于在 Qt 中使用鼠标中键单击和拖动移动整个窗口的主要内容,如果未能解决你的问题,请参考以下文章

Cesium.js禁止三维球鼠标旋转、缩放、鼠标中键拖动

Qt自定义界面边框后,移动鼠标拖动界面,界面会拖到任务栏以下。。。如何解决?

如何使用某个组合键+鼠标移动来调整窗口大小? (如 Linux 中的 Alt+F8)不单击并拖动

Qt设置窗口可拖动

在 Qt 中模拟鼠标功能

如何使用 pytest-qt 自动拖动鼠标?