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.