Как управлять QProgressBar с помощью Signal

Нажатие кнопки запускает цикл 100 раундов. С помощью QLabel.setText() мы обновляем self.label изнутри области действия функции clicked().

Помимо обновления self.label, мы также хотели бы обновить progressbar. Но поскольку progressbar является локальной переменной, мы не можем обновить ее изнутри функции onClick().

введите здесь описание изображения

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_()

person alphanumeric    schedule 06.05.2016    source источник
comment
Почему вы звоните qApp.processEvents() вручную?   -  person anonymous    schedule 06.05.2016
comment
Похоже, что в этом примере не используются потоки или другие процессы... Я предполагаю, что заголовок вопроса неверен? Есть и другие соображения, которые необходимо учитывать, если вы действительно используете потоки.   -  person three_pineapples    schedule 06.05.2016
comment
@three_pineapples: я просто хотел, чтобы код в моем вопросе был как можно более простым. Цель состояла в том, чтобы найти способ управления виджетом извне экземпляра, в котором этот виджет был объявлен, из другого внешнего потока или из другого внешнего процесса.   -  person alphanumeric    schedule 06.05.2016


Ответы (2)


Объявите индикатор выполнения как:

self.progressbar = ProgressBar(self)
person anonymous    schedule 06.05.2016

Код объявляет локальный объект progressbar, подключенный к пользовательскому «customSignal», используя:

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

с четырьмя аргументами, переданными в QtCore.QObject.connect().

Первый аргумент self — это объект, который будет излучать сигнал. Поскольку функция, которая будет выполнять «обработку каждую секунду в спящем режиме», объявлена ​​в основном экземпляре Dialog, мы передаем здесь self.

Второй аргумент — это имя самого сигнала: «customSignal».

Объект progressbar используется как третий, а его метод setValue как четвертый последний аргумент.

введите здесь описание изображения

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_()

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

Вот вариант того же решения, за исключением ссылки на метод progressbar. время импорта

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_()

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

Этот код теперь связывает пользовательский сигнал с функцией, называемой Slot в 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()
person alphanumeric    schedule 06.05.2016