I am currently in the process of creating a class that produces a pyqtSignal(int) and pyqtSlot(int). The difficulty lies in creating a signal that emits a specific value.
Suppose I want to produce something similar to the following simple example:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal, pyqtSlot)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
@pyqtSlot(int)
def on_sld_valueChanged(self, value):
self.lcd.display(value)
self.printLabel(value)
def initUI(self):
self.lcd = QLCDNumber(self)
self.sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(self.lcd)
vbox.addWidget(self.sld)
self.setLayout(vbox)
self.sld.valueChanged.connect(self.on_sld_valueChanged)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
My first question for the above code is:
- Why use the pyqtSlot() decorator at all when removing
pyqtSlot(int)
has no effect on the code? - Can you give an example of when it would be necessary?
For specific reasons, I would like to produce my own signal using the pyqtSignal() factory and am given decent documentation here. The only problem however, is that the very simple example does not give a solid foundation for how to emit specific signals.
Here is what I am trying to do but have found myself lost:
- Create a metaclass that allows for the implementation of many different types of QWidget subclasses.
- Have the metaclass produce its own signal that can be called from outside the class.
This is what I am going for:
from PyQt5.QtWidgets import QPushButton, QWidget
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QSlider
def template(Q_Type, name: str, *args):
class MyWidget(Q_Type):
def __init__(self) -> None:
super().__init__(*args)
self._name = name
def setSignal(self,type):
self.signal = pyqtSignal(type)
def callSignal(self):
pass
return MyWidget
As you can see. I give the widget a name because I find this to be useful, and I also try to instantiate the QWidget from within the class to simplify code.
This is how I would like a main class to produce the widgets from the first example:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal, pyqtSlot)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
@pyqtSlot(int)
def sld_valChanged(self, value):
self.lcd.display(value)
self.printLabel(value)
def initUI(self):
#instantiate the QWidgets through template class
self.lcd = template(QLCDNumber,'lcd_display')
self.sld = template(QSlider, 'slider', Qt.Horizontal)
#create signal
#self.sld.setSignal(int)
vbox = QVBoxLayout()
vbox.addWidget(self.lcd)
vbox.addWidget(self.sld)
self.setLayout(vbox)
#connect signal - this won't send the value of the slider
#self.sld.signal.connect(self.sld_valChanged)
self.sld.valueChanged.connect(self.sld_valChanged)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
There are only 2 problems that need to be solved here:
- The template metaclass is set up incorrectly, and I am unable to instantiate the QWidget from within the metaclass. The
Q_Type
is telling me that its type isPyQt5.QtCore.pyqtWrapperType
when it should bePyQt5.QtWidgets.QSlider
. - Even though I am creating a newSignal via the templated class, how do I get the
QSlider
to send the changed value that I want it to send. I believe this is whereemit()
comes into play but do not have enough knowledge as to how it is useful. I know I could make some sort of function callself.sld.emit(35)
if I would like the signal to pass the value 35 to the slot function. The question becomes not how but where should I implement this function?
I may be totally offbase and overthinking the solution, feel free to correct my code so that I can have my signal emit the value of the slider.