Search code examples
pythonpyqt5mouseeventqtwidgets

How to enable mouse tracking on movement in QTabWidget


I have a QApplication in PyQt5 that tracks the mouse movement and updates a label with x & y coordinates. This works as expected when the mouse movement occurs within the main QDialog. However, when the mouse moves into a QTabWidget the label updating stops. It will resume again if I click (hold) and drag the mouse, but stops again once the left button is released. Why is this, and how can I change my code so the label continues to update when the mouse is moved into the QTabWidget?

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class MyForm(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.show()

    def mouseMoveEvent(self, event):
        x = event.x()
        y = event.y()
        text = "x: {0}, y: {1}".format(x, y)
        self.ui.labelTracking.setText(text)     

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(653, 450)
        Dialog.setMouseTracking(True)
        self.tabWidget = QtWidgets.QTabWidget(Dialog)
        self.tabWidget.setGeometry(QtCore.QRect(160, 0, 481, 451))
        self.tabWidget.setMouseTracking(True)
        self.tabWidget.setObjectName("tabWidget")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.tabWidget.addTab(self.tab, "")
        self.labelTracking = QtWidgets.QLabel(Dialog)
        self.labelTracking.setGeometry(QtCore.QRect(10, 80, 131, 61))
        self.labelTracking.setMouseTracking(True)
        self.labelTracking.setText("")
        self.labelTracking.setObjectName("labelTracking")

        self.retranslateUi(Dialog)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Dialog", "Test Tab"))


if __name__=="__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MyForm()
    w.show()
    sys.exit(app.exec_())

Solution

  • It will work if you enable mouse tracking on the widget inside the QTabWidget, and set its mouseMoveEvent to the one you defined.

    class MyForm(QtWidgets.QDialog):
        def __init__(self):
            super().__init__()
            self.ui = Ui_Dialog()
            self.ui.setupUi(self)
            self.ui.tab.mouseMoveEvent = self.mouseMoveEvent
            self.show()
    
        def mouseMoveEvent(self, event):
            pos = event.windowPos().toPoint()
            x = pos.x()
            y = pos.y()
            text = "x: {0}, y: {1}".format(x, y)
            self.ui.labelTracking.setText(text)   
    

    And in Ui_Dialog include self.tab.setMouseTracking(True). QMouseEvent.windowPos() is used instead of pos() to get the coordinates relative to the window that received the event, as otherwise it would be relative to the tab widget when hovering over it.