I'm trying to capture the cursor coordinates as the mouse is moved within a QWidget
by reimplementing QWidget::mouseMoveEvent()
. With mouse tracking enabled, mouse move events are generated as I move the cursor around the main widget. However, when the cursor is placed over a child widget the mouse move events cease to fire.
Mouse press/release events work while the cursor is over the same child widget, and move events are firing correctly if the mouse button is held. I've tried enabling mouse tracking on the children too, but it doesn't seem to make a difference. How can I trigger mouse move events when the mouse is over a child widget?
Here's a minimum working example that demonstrates the problem:
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_())
When the mouse is moved outside of the QTabWidget
the mouse coordinates are printed as expected. Inside of it nothing happens unless the mouse button is held.
The problem with your code is that you need to enable mouse tracking for all widgets explicitly. You can do this by iterating over all children of your main widget, and calling setMouseTracking(True)
for each of them. Here I've overridden setMouseTracking()
to do just that:
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_())
LAST UPDATED 19 / 8 / 2014 14 : 37 Fixed tab bar isn't track mouse move event. (your can see in my code)
I also suggest implemented QWidget.mouseMoveEvent (self, QMouseEvent)
as your do. But not only root widget only because it track area of interesting widget, so your have to set mouse move event all widget can track your in your application. So, create delegate method to connect them all and if your have any signal form mouse move event, get current point of mouse it. like this;
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_())
Regards,
I had the same issue and found the answer here:
self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With