I am trying implement a feature such that when a mouse is clicked on the gui, a function is triggered
Below is my mouse click detection, it doesn't work when I click on any part of the gui
from PySide.QtCore import *
from PySide.QtGui import *
import sys
class Main(QWidget):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
layout = QHBoxLayout(self)
layout.addWidget(QLabel("this is the main frame"))
layout.gui_clicked.connect(self.anotherSlot)
def anotherSlot(self, passed):
print passed
print "now I'm in Main.anotherSlot"
class MyLayout(QHBoxLayout):
gui_clicked = Signal(str)
def __init__(self, parent=None):
super(MyLayout, self).__init__(parent)
def mousePressEvent(self, event):
print "Mouse Clicked"
self.gui_clicked.emit("emit the signal")
a = QApplication([])
m = Main()
m.show()
sys.exit(a.exec_())
This is my goal
Mouseclick.gui_clicked.connect(do_something)
Any advice would be appreciated
Define mousePressEvent
inside Main
:
from PySide.QtCore import *
from PySide.QtGui import *
import sys
class Main(QWidget):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
layout = QHBoxLayout(self)
layout.addWidget(QLabel("this is the main frame"))
def mousePressEvent(self, QMouseEvent):
#print mouse position
print QMouseEvent.pos()
a = QApplication([])
m = Main()
m.show()
sys.exit(a.exec_())
This can get complicated depending on your needs. In short, the solution is an eventFilter
installed on the application. This will listen the whole application for an event. The problem is "event propagation". If a widget doesn't handle an event, it'll be passed to the parent (and so on). You'll see those events multiple times. In your case, for example QLabel
doesn't do anything with a mouse press event, therefore the parent (your main window) gets it.
If you actually filter the event (i.e. you don't want the original widget to respond to the event), you won't get that problem. But, I doubt that this is your intent.
A simple example for just monitoring:
import sys
from PySide import QtGui, QtCore
class MouseDetector(QtCore.QObject):
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.MouseButtonPress:
print 'mouse pressed', obj
return super(MouseDetector, self).eventFilter(obj, event)
class MainWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
layout = QtGui.QHBoxLayout()
layout.addWidget(QtGui.QLabel('this is a label'))
layout.addWidget(QtGui.QPushButton('Button'))
self.setLayout(layout)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mouseFilter = MouseDetector()
app.installEventFilter(mouseFilter)
main = MainWindow()
main.show()
sys.exit(app.exec_())
You can see that, clicking on the QLabel
will give you something like:
mouse pressed <PySide.QtGui.QLabel object at 0x02B92490>
mouse pressed <__main__.MainWindow object at 0x02B92440>
Because, QLabel
receives the event and since it doesn't do anything with it, it's ignored and passed to the parent (MainWindow
). And it's caught by the filter/monitor again.
Clicking on the QPushButton
doesn't have any problem because it uses that event and does not pass to the parent.
PS: Also note that this can cause performance problems since you are inspecting every single event in the application.