PyQt5: How can I connect a QPushButton to a slot?

Ian Traum picture Ian Traum · Nov 13, 2013 · Viewed 35.7k times · Source

Okay, so pretty much every tutorial/understandable-written-in-human-language-documentation is for PyQt4. But, PyQt5 changed how the whole 'connect button to a slot' works, and I still can't figure it out how to do it.

I did a quick gui in QtDesigner, and I have a QPushButton and a label. When I click the button, I want the text on the label to change. in C++ in QtDesigner, It's easy to connect the two. But I have to write it all in python.

I convert .ui file with pyuic5 to .py file. There, in Ui_MainWindow class, I can see setupUi method, that initializes self.button as follows

self.testButton = QtWidgets.QPushButton(self.centralWidget)
self.testButton.setObjectName("newGame")

then, at the end of the method,

QtCore.QMetaObject.connectSlotsByName(MainWindow)

is called, but, to be honest, I can't figure out what it does and what it connects to where.

in Main class, inheriting from QMainWindow, i write a following method

@pyqtSlot(name='change')
def change_text(self):
    self.ui.testLabel.setText("Button Clicked!")

And i can't figure out how to connect the button signal to that slot. In pyqt4 I could set it up manually by doing button.clicked.connect(self.change_text), but as I've found out, PyQt5 obsoleted and discarded such simple set-up.

Please, can anybody help me with that one?

Answer

ekhumoro picture ekhumoro · Nov 14, 2013

I don't know where you got the idea that "PyQt5 changed how the whole 'connect button to a slot' works", but it is completely and utterly wrong. There have been no such changes, as can be readily seen from the official PyQt documentation:

But even without reading any documentation, it's easy enough to test for yourself. For example, in the following script, just switch comments on the first two lines, and it will run just the same:

# from PyQt5.QtWidgets import (
from PyQt4.QtGui import (
    QApplication, QWidget, QVBoxLayout, QPushButton, QLabel,
    )

class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.button = QPushButton('Test', self)
        self.label = QLabel(self)
        self.button.clicked.connect(self.handleButton)
        layout = QVBoxLayout(self)
        layout.addWidget(self.label)
        layout.addWidget(self.button)

    def handleButton(self):
        self.label.setText('Button Clicked!')

if __name__ == '__main__':

    import sys
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

As for the other points: at your current state of knowledge, I would say you can safely ignore connectSlotsByName and pyqtSlot. Although they have their uses (see the above docs for details), there's very rarely any real need to use them in 95% of applications.

For your specific case, the syntax is simply:

    self.testButton.clicked.connect(self.change_text)
    ...

def change_text(self):
    self.ui.testLabel.setText("Button Clicked!")