How to make a signal - Anderas2/Heroscribe2 GitHub Wiki
Some signals are missing from some widgets, especially from QGraphicsScene. That's annoying if you want, for example, to get a mouse click. Those signals are there, prepared, but not implemented for whatever reason.
I managed to get it working like this. Copy and paste to source code editor for readability.
I use here the "prepared but not implemented" method mouseReleaseEvent. It gets automatically
some details about cursor position and family. I call this object MouseEvent in my code.
There is a list of available events under "protected functions" in the QWidget documentation.
# necessary imports....
import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QDialog, QGraphicsScene, QGraphicsView, QGraphicsRectItem
from PyQt5.QtCore import QRectF, QObject
from monster_editor import Ui_Dialog as monstergui # get my pyqt5designer made gui over here
Second step, make your own class with your wish-for-class as parent and define signals inside. I use item_clicked and message_in_a_bottle. Both name are freely choosable.
Important is that the "item_clicked" is then "connected" to self.mouseReleaseEvent in the init method; and somewhere in the class, mouseReleaseEvent must be defined.
class myGraphicsScene(QGraphicsScene):
item_clicked = QtCore.pyqtSignal(object) # custom selfmade signal
message_in_a_bottle = QtCore.pyqtSignal(object) # another custom selfmade signal
# initialize selfmade class with parent
def __init__(self, parent = None):
super(myGraphicsScene, self).__init__(parent)
# connect mouse click with my own method.
self.item_clicked.connect(self.mouseReleaseEvent)
def mouseReleaseEvent(self, MouseEvent):
print("Scene Mouse Release detected") # do whatever selfmade code
# raise whatever you like. You can also raise the MouseEvent or self or nothing...
self.message_in_a_bottle.emit("scene click released")
Important: Don't raise the same signal in the connected method - as that signal is connected to the method, it is calling itself, an endless loop.
Later, in the "real code", you can connect your selfmade signals to a method you like - as long as they are sent out of the class via "emit", others can get them.
# define Monster data edit dialog
class MonsterData(QDialog):
def __init__(self, parent = None):
super(MonsterData, self).__init__(parent)
self.ui = monstergui()
self.ui.setupUi(self)
# initialize monster picture
self.scene_monpic = myGraphicsScene() #use my graphicsscene, not the original one
self.ui.graphicsView.setScene(self.scene_monpic)
self.scene_monpic.message_in_a_bottle.connect(self.update_monsterpic)
def update_monsterpic(self):
print("arrived after the click event")
If the signal raises something and the receiving method is not ready to take it (like my "update_monsterpic"); then the data is lost.
If I'd rewrite my medhod like this update_monsterpic(self, message) then it would receive the message that I sending earlier in the code; in this line: self.message_in_a_bottle.emit("scene click released")
This is also the way how to get the mouse data (position, which button, yaddah yaddah) into your own method.