Home > PyQt5, python > PyQt5: QProgressBar

PyQt5: QProgressBar

23 Aprile 2019

Torna all’indice degli appunti

QProgressBar


Il QProgressBar è un widget che mette a disposizione dell’utente, una barra di avanzamento orizzontale, o verticale.
La progress bar viene utilizzata per indicare all’utente che l’applicazione sta ancora svolgendo una determinata operazione.

Il costruttore è ovviamente QProgressBar e i metodi principali sono:

setMinimum(int): setta il valore minimo della progress bar;
setMaximum(int): setta il valore massimo della progress bar;
setRange(min, max): setta il valore minimo e massimo della progress bar in un unico metodo;
setValue(int): setta il valore di avanzamento della progress bar;
reset: riporta il valore dell’avanzamento della progress bar a zero;

per ottenere i valori impostati in una progress bar, si utilizzano i metodi:

minimum: ritorna il valore minimo impostato per la progress bar;
maximum: ritorna il valore massimo per la progress bar;
value: ritorna il valore di avanzamento della progress bar;

>>> from PyQt5.QtWidgets import QApplication, QProgressBar
>>> app = QApplication([])
>>> pb = QProgressBar()
>>> pb.setMinimum(0)
>>> pb.setMaximum(100)
>>> pb.setValue(50)
>>> pb.minimum()
0
>>> pb.maximum()
100
>>> pb.value()
50
>>> pb.reset()
>>> pb.value()
-1

ORIENTAMENTO

L’orientamento della progress bar è impostabile tramite il metodo setOrientation(Orientation) dove orientation può essere una delle segeunti costanti:

Qt.Horizontal
Qt.Vertical

Il tipo di orientamento pùo essere ottenuto con il metodo orientation.

>>> from PyQt5.QtCore import Qt
>>> pb.setOrientation(Qt.Horizontal)
>>> pb.orientation()
1
>>> pb.setOrientation(Qt.Vertical)
>>> pb.orientation()
2

TESTO PROGRESS BAR

Il formato del testo che appare a fianco della barra di avanzamento, può essere settato con il metodo setFormat(format), dove format può utilizzare i seguenti parametri:

%p: viene sostituito dalla percentuale di completamento;
%v: viene sostituito dal valore di avanzamento della progress bar
%m: viene sostituito dal numero totale di step previsti settati col metodo setMaximum(int);

Infine, per ottenere il formato utilizzato da una progress bar, si utilizza il metodo format.

>>> format = "%v/%m (%p%)"
>>> pb.setFormat(format)
>>> pb.format()
'%v/%m (%p%)'

il testo dell’avanzamento della progress bar si ottiene con il metodo text

>>> pb.text()
'50/100 (50%)'

Se non vogliamo che il testo dell’avanzamento della progress bar sia visibile, possiamo utilizzare il metodo setTextVisible(bool).

SEGNALI

L’unico segnale degno di nota è valueChanged, emesso ad ogni cambio di step:

>>> pb.valueChanged.connect(lambda: print("progress bar value changed to: %s" % pb.value()))
<PyQt5.QtCore.QMetaObject.Connection object at 0x037261B0>
>>> pb.setValue(51)
progress bar value changed to: 51

Vediamo un esempio visivo di una semplice progress bar con un pulsante che avvii l’avanzamento della stessa;

from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import (QWidget, QApplication, QBoxLayout, QPushButton,
                             QProgressBar)
import sys
import time


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setWindowTitle("QProgressBar Example")
        self.central_widget = FormWidget(self) 
        self.setCentralWidget(self.central_widget)
        self.resize(250, 100)


class FormWidget(QWidget):
    def __init__(self, parent):
        super(FormWidget, self).__init__(parent)
        layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.setLayout(layout)
        self.progressbar = QProgressBar()
        self.progressbar.setMaximum(0)
        self.progressbar.setMaximum(200)
        self.progressbar.setFormat("%v/%m (%p%)")
        btn_start = QPushButton("START")
        layout.addWidget(self.progressbar, 0)
        layout.addWidget(btn_start, 0)
        btn_start.clicked.connect(self.on_start)

    def on_start(self):
        maximum = self.progressbar.maximum()
        for n in range(maximum + 1):
            time.sleep(0.02)
            self.progressbar.setValue(n)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

Può capitare ci sia la necessità di passare un argomento allo slot richiamato quando viene emesso un segnale.
Ad esempio, se non avessimo a disposizione il metodo maximum avremmo il problema di passare il valore massimo della progress bar, allo slot dove ci occupiamo dell’avanzamento della progress bar stessa.
Per questo genere di situazioni ci viene incontro la funzione lambda, come nell’esempio di seguito:

from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import (QWidget, QApplication, QBoxLayout, QPushButton,
                             QProgressBar)
import sys
import time


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setWindowTitle("QProgressBar Example")
        self.central_widget = FormWidget(self) 
        self.setCentralWidget(self.central_widget)
        self.resize(250, 100)


class FormWidget(QWidget):
    def __init__(self, parent):
        super(FormWidget, self).__init__(parent)
        maximum = 150
        layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.setLayout(layout)
        self.progressbar = QProgressBar()
        self.progressbar.setMaximum(0)
        self.progressbar.setMaximum(maximum)
        self.progressbar.setFormat("%v/%m (%p%)")
        btn_start = QPushButton("START")
        layout.addWidget(self.progressbar, 0)
        layout.addWidget(btn_start, 0)
        btn_start.clicked.connect(lambda: self.on_start(maximum))  # lambda

    def on_start(self, length):
        for n in range(length + 1):
            time.sleep(0.05)
            self.progressbar.setValue(n)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

PERSONALIZZAZIONE PROGRESS BAR

Mettiamo di voler eliminare il testo a fianco della barra, ma volerlo visualizzare al centro della stessa.
Per fare questo tipo di personalizzazioni, sarebbe sempre meglio sottoclassare la classe QProgressBar.
Creiamo per tanto la nostra sottoclasse come di seguito:

...

class CustomProgressBar(QProgressBar):
    def __init__(self, minimum, maximum):
        super(CustomProgressBar, self).__init__()
        self.setRange(minimum, maximum)
        self.setAlignment(Qt.AlignCenter)
        self._text = "0/0 (0%) Click start..."
        self.setFormat("%v/%m (%p%)")

    def set_text(self, text):
        self._text = text

    def text(self):
        return self._text

    def update(self, step):
        maximum = self.maximum()
        rate = step * 100 / maximum
        string = "{}/{} ({}%)".format(step, maximum, rate)
        time.sleep(0.02)
        self.set_text(string)
        self.setValue(step)
...

Oltre al fatto di inserire i valori minimi a massimi in fase di inizializzazione, accediamo al testo interno della progress bar,
l’argomento _text per modificarlo, creando quindi un metodo ad-hoc set_text(text), ma soprattutto, creiamo un metodo update(step), che aggiorna il valore della progress bar, nonchè il testo al suo interno.

Il codice totale sarà quindi:

from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import (QWidget, QApplication, QBoxLayout, QPushButton,
                             QProgressBar)
from PyQt5.QtCore import Qt
import sys
import time


class CustomProgressBar(QProgressBar):
    def __init__(self, minimum, maximum):
        super(CustomProgressBar, self).__init__()
        self.setRange(minimum, maximum)
        self.setAlignment(Qt.AlignCenter)
        self._text = "0/0 (0%) Click start..."
        self.setFormat("%v/%m (%p%)")

    def set_text(self, text):
        self._text = text

    def text(self):
        return self._text

    def update(self, step):
        maximum = self.maximum()
        rate = step * 100 / maximum
        string = "{}/{} ({}%)".format(step, maximum, rate)
        time.sleep(0.02)
        self.set_text(string)
        self.setValue(step)


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setWindowTitle("QProgressBar Example")
        self.central_widget = FormWidget(self) 
        self.setCentralWidget(self.central_widget)
        self.resize(250, 100)


class FormWidget(QWidget):
    def __init__(self, parent):
        super(FormWidget, self).__init__(parent)
        layout = QBoxLayout(QBoxLayout.TopToBottom)
        self.setLayout(layout)
        self.progressbar = CustomProgressBar(0, 200)
        btn_start = QPushButton("START")
        layout.addWidget(self.progressbar, 0)
        layout.addWidget(btn_start, 0)
        btn_start.clicked.connect(self.on_start)

    def on_start(self):
        max = self.progressbar.maximum()
        for n in range(max + 1):
            self.progressbar.update(n)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())


Torna all’indice degli appunti

Categorie:PyQt5, python Tag: ,
I commenti sono chiusi.