I am attempting to create a simple connection between a signal and slot but have found myself stuck trying to call an extra function. There are 2 options I have come to. Here is the code that calls my class.
(Option 1):
self.flip = MyClass("Flip Image")
self.flip.clicked.connect(self.do_flip)
The QWidget
is then instantiated by my class, whose major purpose is to log the signal made. This is how I believe my class should be implemented:
class MyClass(QPushButton):
def __init__(self, name: str) -> None:
super().__init__(name)
self._name = name
def mousePressEvent(self, *args, **kwargs):
self.log_info()
def log_info(self):
log(self._name)
What I don't understand is why the do_flip
slot is never called? This makes no sense to me, so I instead tried overriding the clicked signal via
(Option 2):
class MyClass(QPushButton):
def __init__(self, name: str) -> None:
super().__init__(name)
self._name = name
def clicked(self, *args, **kwargs):
self.log_info()
#add connect() here?
def log_info(self):
log(self._name)
But with this code I get a friendly AttributeError: 'function' object has no attribute 'connect'
. I can't find any documentation on the clicked
method and how it calls connect. Is there a way for me to make the connection for clicked to the slot or do I have to create my own signal? I find that this will become very useful when trying to override other signals that emit specific values too.
If so this leads me to:
Last Resort - My Own Signal
The class would be called like this:
self.flip = MyClass("Flip Image")
self.flip.mysig.connect(self.do_flip)
And implemented like this:
class MyClass(QPushButton):
mysig = pyqtSignal()
def __init__(self, name: str) -> None:
super().__init__(name)
self._name = name
def mousePressEvent(self, *args, **kwargs):
self.mysig.emit()
self.log_info()
def log_info(self):
log(self._name)
And this works. But I'm not sure my implementation makes sense. It feels kind of hacky. I'd prefer not to use this last resort option, and I'm hoping there is a cleaner option.
In Option 1 you are overriding the mousePressEvent
method of QPushButton
without calling the default implementation using super
, and this I believe is the reason why the clicked
signal is never emitted. For instance:
class MyClass(QPushButton):
def __init__(self, name: str) -> None:
super().__init__(name)
self._name = name
def mousePressEvent(self, event):
self.log_info()
super().mousePressEvent(event)
def log_info(self):
log(self._name)
In Option 2 you are declaring clicked
as a normal python callable while instead it should be a pyqtSignal()
. Also this is definitely not the way to go.
The correct way to achieve what you need is to use multiple slots for the same signal, i.e:
class MyClass(QPushButton):
def __init__(self, name: str) -> None:
super().__init__(name)
self._name = name
@pyqtSlot()
def log_info(self):
log(self._name)
self.flip = MyClass("Flip Image")
self.flip.clicked.connect(self.do_flip)
self.flip.clicked.connect(self.flip.log_info)