首页 文章

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

提问于
浏览
6

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

鼠标按下/释放事件在光标位于同一子窗口小部件上时起作用,如果按住鼠标按钮,则移动事件将正确触发 . 我似乎有所作为 . How can I trigger mouse move events when the mouse is over a child widget?

这是演示问题的最小工作示例:

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 之外时,将按预期打印鼠标坐标 . 除非按住鼠标按钮,否则没有任何反应 .

3 回答

  • 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_())
    
  • 0

    LAST UPDATED 19 / 8 / 2014 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_())
    

    问候,

  • 1

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

相关问题