Saar Drimer
Saar Drimer

Reputation: 1191

Using QTimer.singleShot correctly

I have the following PySide application, where the intended functionality is to have the text of the number_button be updated every 5 seconds, counting from 0 to 9 once the start_button has been pressed.


import sys
from PySide import QtGui, QtCore

class Example(QtGui.QWidget):

    def __init__(self, parent=None):
        super(Example, self).__init__(parent)

        self.app_layout = QtGui.QVBoxLayout()
        self.setLayout(self.app_layout)

        self.setGeometry(300, 300, 50, 50)

        self.count_to = 10
        self.delay = 5000

        self.timer = QtCore.QTimer(self)
        self.timer.setSingleShot(True)

        # start button
        start_button = QtGui.QPushButton()
        start_button.setText('START')
        start_button.clicked.connect(self.startCount)
        self.app_layout.addWidget(start_button)

        # number button
        self.number_button = QtGui.QPushButton()
        self.number_button.setText('0')
        self.app_layout.addWidget(self.number_button)



    def startCount(self):

        def updateButtonCount():
            self.number_button.setText("%s" % count)

        for count in range(0, self.count_to):
            self.timer.singleShot(self.delay, updateButtonCount)


def main():

    app = QtGui.QApplication(sys.argv)
    example = Example()
    example.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

However, this results in a 9 appearing after 6 seconds without the intermediate numbers showing at all. I'm pretty sure that the problem is that while the .singleShot is running, count has already been incremented to its maximum value (9).

I can think of a few hack to make this work as intended, but I'd like to fix it in the most effective and appropriate way.

Upvotes: 7

Views: 24080

Answers (1)

estebro
estebro

Reputation: 1027

As mentioned in the QTimer PySide documentation, what you need is a QTimer that will repeatedly time out (every 5 seconds in your case) and call the function updateButtonCount once for every timeout - as mentioned by aruisdante. Take a look at this:

timer = QTimer()  # set up your QTimer
timer.timeout.connect(self.updateButtonCount)  # connect it to your update function
timer.start(5000)  # set it to timeout in 5000 ms

With some modifications, the previous code should help you achieve the functionality you want. Keep in mind, timer.start(5000) only sets up one timeout to occur in 5000 ms, or 5 seconds, and your updateButtonCount function should include this line at the end if the QTimer is to timeout again.

I hope that helps. Feel free to comment if something is not clear.

Upvotes: 7

Related Questions