PDA

View Full Version : PyQt4 QGraphicsView and 'pressed' signal



splondike
8th October 2009, 08:08
Hello, i'm having trouble detecting the 'pressed' signal from a QGraphicsView using the signal/slots framework in PyQt4 (v4.5.4, Qt v4.5.2).

The attached code perhaps best illustrates my problem. The default event handler 'mousePressEvent' fires as expected, but the slot 'slotPressEvent' does not respond to the 'pressed' signal. Can anyone see what the problem is?

The workaround i'm currently using is commented out on line 13, emitting the 'pressed' signal from the 'mousePressEvent' handler. In my actual application I am also going to trap the 'released' signal on the QGraphicsView, which I am currently doing using the same workaround.

I expect i'm not understanding something about Qt's signals/events. Coming from experience with Javascript's various event listeners may have confused me as to how they actually work. In JS you can attach a single handler directly as a property of the object button.click, or multiple handlers using: button.addEventListener('click', function). I think of 'mousePressEvent' as being equivalent to button.click, and signals/slots to addEventListener. Is this right?

scascio
8th October 2009, 08:33
In fact, responding with mouse events does not requires the use of SIGNAL/SLOT mechanism.

I dont know Python but in C++, you need to derived your widget and reimplement the method QWidget::mousePressEvent(QMouseEvent).
Be aware of QEvent derived argument .

Then, you are free to emit other signals for your own design.

In the sample you provided, I notice that :
* you emit a signal in response of pressEvent but why not direclty call the function you want to be executed
* the arguments between the signal you emitted and the slot you have connected to it dont match. It cant work. Don't you have any warnings somewhere about failed connect?

splondike
8th October 2009, 13:34
Thanks for your reply. In my actual application i'm trying to use signals/slots to combine the functions dealing with remapping the QGraphicsView drag button from left to middle. The following is the relevant code i've lifted from my application:



#TODO: Make signals work properly
def mousePressEvent(self, event):
self.emit(SIGNAL("pressed"), (event))
QtGui.QGraphicsView.mousePressEvent(self, event)
def mouseReleaseEvent(self, event):
self.emit(SIGNAL("released"), (event))
QtGui.QGraphicsView.mouseReleaseEvent(self, event)
######

#Assigned via self.connect(self, SIGNAL('pressed'), self.grabCanvas) in __init__
def grabCanvas(self, event):
if event.buttons() == QtCore.Qt.MidButton:
origMode = self.dragMode()
self.setDragMode(self.ScrollHandDrag)
#Send a fake LMB press, TODO: Disable scene's selection of objects
fake_event = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonPress, event.pos(),
QtCore.Qt.LeftButton, QtCore.Qt.LeftButton, QtCore.Qt.KeyboardModifiers())
QtGui.QGraphicsView.mousePressEvent(self, fake_event)

#Add a handler to catch the mouse up event
def revert(event):
self.setDragMode(origMode)
self.disconnect(self, SIGNAL("released"), revert)

self.connect(self, SIGNAL("released"), revert)



As you can perhaps see, i'm trying to make a temporary slot to reset some parameters when the button is released. I felt the most elegant and unobtrusive way of doing this would be using signals/slots rather than two event listeners and a bunch of shared flags (like middleButtonPressed, originalDragMode etc.).