an1ge
an1ge

Reputation: 43

pyQt5: Cannot connect QSpinBox::valueChanged(int)

I am new to Python and Qt. Currently, I am trying to build the UI for a larger application, but I am running into problems regarding signals and slots.

Here is my code:

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QObject, pyqtSlot
import sys


class Ui_configDialog(QtWidgets.QDialog):
    def __init__(self):
        super(Ui_configDialog, self).__init__()

        self.setupUi()

    def setupUi(self):
        self.setObjectName("configDialog")
        self.setWindowModality(QtCore.Qt.WindowModal)
        self.resize(425, 380)

        row1 = DataRow(self)

        self.show()


class DataRow:
    def __init__(self, dialog):
        rect = QtCore.QRect(10, 40, 91, 30)

        self.text_fRep = QtWidgets.QSpinBox(dialog)
        self.text_fRep.setGeometry(rect.translated(100, 0))
        self.connect_signal()

    @pyqtSlot(int)
    def fRep_changed(self, value):
        print(value)

    def connect_signal(self):
        self.text_fRep.valueChanged.connect(self.fRep_changed)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    dialog = Ui_configDialog()
    sys.exit(app.exec_())

What I am trying to achieve is, that the slot fRep_changed is called whenever the value of the QSpinBox object is changed. But with this code I receive a compile error:

QObject::connect: Cannot connect QSpinBox::valueChanged(int) to (null)::fRep_changed(int)
TypeError: connect() failed between valueChanged(int) and fRep_changed()

I cannot see, why I shouldn't be able to connect the signal to the slot.

I also removed the @pyqtSlot(int). The application starts, but nothing happens when the value is changed.

Thank you for your help in advance!

Upvotes: 1

Views: 3600

Answers (1)

eyllanesc
eyllanesc

Reputation: 243897

Your code has 2 errors, the first one is that the slots are only implemented within the classes that inherit from QObject, so the easiest thing is for your class to inherit from QObject. The second you will see after making the previous change, it will happen that even if you change the value of QSpinBox will never be called to the slot, and this happens because the collector deletes the object of row1 of the DataRow class, the solution is simple, you just have to make row a member of the class through self, ie change row1 by self.row1

class Ui_configDialog(QtWidgets.QDialog):
    def __init__(self):
        super(Ui_configDialog, self).__init__()

        self.setupUi()

    def setupUi(self):
        self.setObjectName("configDialog")
        self.setWindowModality(QtCore.Qt.WindowModal)
        self.resize(425, 380)

        self.row1 = DataRow(self)

        self.show()


class DataRow(QObject):
    def __init__(self, dialog, parent=None):
        QObject.__init__(self, parent)

        rect = QtCore.QRect(10, 40, 91, 30)

        self.text_fRep = QtWidgets.QSpinBox(dialog)
        self.text_fRep.setGeometry(rect.translated(100, 0))
        self.connect_signal()

    @pyqtSlot(int)
    def fRep_changed(self, value):
        print(value)

    def connect_signal(self):
        self.text_fRep.valueChanged.connect(self.fRep_changed)

Upvotes: 4

Related Questions