How to control QProgressBar with Signal

百般思念 提交于 2019-12-01 07:48:55

问题


Pushing the button starts 100 rounds cycle. With QLabel.setText() we update self.label from inside of scope of clicked() function.

Aside from updating self.label we would like to update the progressbar as well. But since progressbar is a local variable we can't update it from inside of onClick() function.

import time

class ProgressBar(QtGui.QProgressBar):
    def __init__(self, parent=None, total=20):
        super(ProgressBar, self).__init__(parent=parent)

        self.setMinimum(1)
        self.setMaximum(105)        
        self.setTextVisible(True) 

    def set_to_value(self, value):
        self.setValue(value)
        QtGui.qApp.processEvents()

    def closeEvent(self, event):
        self._active=False


class Dialog(QtGui.QDialog):
    def __init__(self):
        super(QtGui.QDialog,self).__init__()

        layout = QtGui.QVBoxLayout()
        self.setLayout(layout)
        self.label = QtGui.QLabel('idle...')
        layout.addWidget(self.label)

        progressbar = ProgressBar(self)
        layout.addWidget(progressbar) 

        button = QtGui.QPushButton('Process')
        button.clicked.connect(self.onClick)
        layout.addWidget(button) 

    def onClick(self):
        for i in range(101):
            message = '...processing %s of 100'%i
            self.label.setText(message)
            QtGui.qApp.processEvents()
            time.sleep(1)


if __name__ == '__main__':
    app = QtGui.QApplication([])
    dialog = Dialog()
    dialog.resize(300, 100)
    dialog.show()
    app.exec_()

回答1:


Declare the progress bar as:

self.progressbar = ProgressBar(self)



回答2:


The code declares a local progressbar object connected to a custom 'customSignal` using:

QtCore.QObject.connect(self, QtCore.SIGNAL("customSignal(int)"), progressbar, QtCore.SLOT("setValue(int)"))

with four arguments passed to QtCore.QObject.connect().

The first argument self is the object that will be emitting the signal. Since the function that will do the "sleep-every-second-processing" is declared under the main Dialog instance we pass self here.

The second argument is the name of the signal itself: 'customSignal'.

The progressbar object is used as third and its method setValue as fourth last argument.

class ProgressBar(QtGui.QProgressBar):
    def __init__(self, parent=None):
        super(ProgressBar, self).__init__(parent=parent)

class Dialog(QtGui.QDialog):
    def __init__(self):
        super(QtGui.QDialog,self).__init__()
        layout = QtGui.QVBoxLayout()
        self.setLayout(layout)
        self.label = QtGui.QLabel('idle...')
        layout.addWidget(self.label)

        progressbar = ProgressBar(self)
        QtCore.QObject.connect(self, QtCore.SIGNAL("customSignal(int)"), progressbar, QtCore.SLOT("setValue(int)"))

        layout.addWidget(progressbar) 

        button = QtGui.QPushButton('Process')
        button.clicked.connect(self.clicked)
        layout.addWidget(button) 

    def clicked(self):
        for value in range(101):
            message = '...processing %s of 100'%value
            self.label.setText(message)
            self.emit(QtCore.SIGNAL("customSignal(int)"), value)
            QtGui.qApp.processEvents()
            time.sleep(1)


if __name__ == '__main__':
    app = QtGui.QApplication([])
    dialog = Dialog()
    dialog.resize(300, 100)
    dialog.show()
    app.exec_()

--------------------

Here is variation of the same solution except linking to the progressbar method. import time

class ProgressBar(QtGui.QProgressBar):
    def __init__(self, parent=None):
        super(ProgressBar, self).__init__(parent=parent)

    def set_to_value(self, value):
        self.setValue(value)
        QtGui.qApp.processEvents()
        return True

    def closeEvent(self, event):
        self._active=False

class Dialog(QtGui.QDialog):
    def __init__(self):
        QtGui.QDialog.__init__(self, parent=None)
        layout = QtGui.QVBoxLayout()
        self.setLayout(layout)
        self.label = QtGui.QLabel('idle...')
        layout.addWidget(self.label)

        progressbar = ProgressBar(self)
        QtCore.QObject.connect(self, QtCore.SIGNAL("customSignal(int)"), progressbar.set_to_value )
        layout.addWidget(progressbar) 

        button = QtGui.QPushButton('Process')
        button.clicked.connect(self.clicked)
        layout.addWidget(button) 

    def clicked(self):
        for value in range(101):
            message = '...processing %s of 100'%value
            self.label.setText(message)
            self.emit(QtCore.SIGNAL("customSignal(int)"), value)
            QtGui.qApp.processEvents()
            time.sleep(1)

if __name__ == '__main__':
    app = QtGui.QApplication([])
    dialog = Dialog()
    dialog.resize(300, 100)
    dialog.show()
    app.exec_()

======================

This code now links a custom signal to a function referred as Slot in Qt.

from PySide import QtCore, QtGui
import time

class ProgressBar(QtGui.QProgressBar):
    def __init__(self, parent=None):
        super(ProgressBar, self).__init__(parent=parent)

    @QtCore.Slot(int)
    def set_to_value(self, value):
        self.setValue(value)
        QtGui.qApp.processEvents()
        return True

    def closeEvent(self, event):
        self._active=False

class Dialog(QtGui.QDialog):
    def __init__(self):
        QtGui.QDialog.__init__(self, parent=None)
        layout = QtGui.QVBoxLayout()
        self.setLayout(layout)
        self.label = QtGui.QLabel('idle...')
        layout.addWidget(self.label)

        progressbar = ProgressBar(self)
        # QtCore.QObject.connect(self, QtCore.SIGNAL("customSignal(int)"), progressbar.set_to_value )
        QtCore.QObject.connect(self, QtCore.SIGNAL("customSignal(int)"), progressbar, QtCore.SLOT("set_to_value(int)"))

        layout.addWidget(progressbar) 

        button = QtGui.QPushButton('Process')
        button.clicked.connect(self.clicked)
        layout.addWidget(button) 

    def clicked(self):
        for value in range(101):
            message = '...processing %s of 100'%value
            self.label.setText(message)
            self.emit(QtCore.SIGNAL("customSignal(int)"), value)
            QtGui.qApp.processEvents()
            time.sleep(1)

if __name__ == '__main__':
    dialog = Dialog()
    dialog.resize(300, 100)
    dialog.show()


来源:https://stackoverflow.com/questions/37063664/how-to-control-qprogressbar-with-signal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!