当光标在子窗口小部件上时,QWidget :: mouseMoveEvent不会触发

时间:2014-08-18 16:55:12

标签: python qt pyqt

我正在尝试通过重新实现QWidget,在QWidget::mouseMoveEvent()内移动鼠标时捕捉光标坐标。启用鼠标跟踪后,当我将光标移动到主窗口小部件时,会生成鼠标移动事件。但是,当光标放在子窗口小部件上时,鼠标移动事件将停止触发。

鼠标按下/释放事件在光标位于同一子窗口小部件上时起作用,如果按住鼠标按钮,则移动事件将正确触发。我也尝试过对孩子们进行鼠标跟踪,但似乎没有什么区别。 当鼠标悬停在子窗口小部件上时,如何触发鼠标移动事件?

以下是演示此问题的最低工作示例:

import sys
from PyQt4 import QtCore, QtGui

class MyWindow(QtGui.QWidget) :
    def __init__(self):
        QtGui.QWidget.__init__(self)
        tabs = QtGui.QTabWidget()
        tab1 = QtGui.QWidget()
        tab2 = QtGui.QWidget()
        tabs.addTab(tab1, "Tab 1")
        tabs.addTab(tab2, "Tab 2")
        layout = QtGui.QVBoxLayout()
        layout.addWidget(tabs)
        self.setLayout(layout)
        self.setMouseTracking(True)

    def mouseMoveEvent(self, event):
        print 'mouseMoveEvent: x=%d, y=%d' % (event.x(), event.y())


app = QtGui.QApplication(sys.argv)
window = MyWindow()
window.setFixedSize(640, 480)
window.show()
sys.exit(app.exec_())

当鼠标移动到QTabWidget之外时,鼠标坐标将按预期打印。除非按住鼠标按钮,否则没有任何反应。

4 个答案:

答案 0 :(得分:11)

您的代码存在的问题是您需要明确地为所有小部件启用鼠标跟踪。您可以通过迭代主窗口小部件的所有子项,并为每个子窗口调用setMouseTracking(True)来完成此操作。在这里,我重写setMouseTracking()来做到这一点:

import sys
from PyQt4 import QtCore, QtGui

class MyWindow(QtGui.QWidget) :
    def __init__(self):
        QtGui.QWidget.__init__(self)
        tabs = QtGui.QTabWidget()
        tab1 = QtGui.QWidget()
        tab2 = QtGui.QWidget()
        tabs.addTab(tab1, "Tab 1")
        tabs.addTab(tab2, "Tab 2")
        layout = QtGui.QVBoxLayout()
        layout.addWidget(tabs)
        self.setLayout(layout)
        self.setMouseTracking(True)

    def setMouseTracking(self, flag):
        def recursive_set(parent):
            for child in parent.findChildren(QtCore.QObject):
                try:
                    child.setMouseTracking(flag)
                except:
                    pass
                recursive_set(child)
        QtGui.QWidget.setMouseTracking(self, flag)
        recursive_set(self)

    def mouseMoveEvent(self, event):
        print 'mouseMoveEvent: x=%d, y=%d' % (event.x(), event.y())


app = QtGui.QApplication(sys.argv)
window = MyWindow()
window.setFixedSize(640, 480)
window.show()
sys.exit(app.exec_())

答案 1 :(得分:1)

上次更新2014/8/8 14:37 固定标签栏不是跟踪鼠标移动事件。 (你可以在我的代码中看到)


我还建议您实施QWidget.mouseMoveEvent (self, QMouseEvent)。但不仅仅是根小部件,因为它跟踪有趣小部件的区域,因此您必须设置鼠标移动事件,所有小部件都可以在您的应用程序中跟踪您的。因此,创建委托方法将它们全部连接起来,如果你有任何信号形成鼠标移动事件,那么获取它的当前点。像这样;

import sys
from PyQt4 import QtGui

class QCustomWidget (QtGui.QWidget):
    def __init__ (self, parent = None):
        super(QCustomWidget, self).__init__(parent)
        self.myQTabWidget = QtGui.QTabWidget(self)
        self.my1QWidget   = QtGui.QWidget()
        self.my2QWidget   = QtGui.QWidget()
        self.myQTabWidget.addTab(self.my1QWidget, 'Tab 1')
        self.myQTabWidget.addTab(self.my2QWidget, 'Tab 2')
        myQLayout = QtGui.QVBoxLayout()
        myQLayout.addWidget(self.myQTabWidget)
        self.setLayout(myQLayout)
        self.setMouseMoveEventDelegate(self)
        self.setMouseMoveEventDelegate(self.myQTabWidget)
        self.setMouseMoveEventDelegate(self.myQTabWidget.tabBar())
        self.setMouseMoveEventDelegate(self.my1QWidget)
        self.setMouseMoveEventDelegate(self.my2QWidget)

    def setMouseMoveEventDelegate (self, setQWidget):
        def subWidgetMouseMoveEvent (eventQMouseEvent):
            currentQPoint = self.mapFromGlobal(QtGui.QCursor.pos())
            print currentQPoint.x(), currentQPoint.y()
            QtGui.QWidget.mouseMoveEvent(setQWidget, eventQMouseEvent)
        setQWidget.setMouseTracking(True)
        setQWidget.mouseMoveEvent = subWidgetMouseMoveEvent

appQApplication = QtGui.QApplication(sys.argv)
windowQCustomWidget = QCustomWidget()
windowQCustomWidget.setFixedSize(640, 480)
windowQCustomWidget.show()
sys.exit(appQApplication.exec_())

此致

答案 2 :(得分:0)

我会尝试通过在调用QTabWidget构造函数时传递self来使您的QTabWidget成为MyWindow的逻辑子代。还为选项卡窗口小部件的子项传递父项,但将选项卡窗口小部件变量tabs传递给它们各自的构造函数。如果没有像这样声明的子层次结构,事件可能无法正确转发到包含的小部件,因为它的" children"从qt场景图/事件队列的角度来看,它将被视为在您的类顶层绘制的单独小部件。

答案 3 :(得分:-1)

我遇到了同样的问题,并找到了答案here

self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)