PyQt progressbar
Still worried about finding Python to do a variety of progress bar beautification?
In this article you learn how to use the QProgressbar and how to create theme variations.
The QProgressBar applications will do some delay operations, which will cause the main thread to get stuck in the UI: The main thread will be waiting for delays, which causes the whole program to hang. That would make the whole program unresponsive.
Threads in PyQt can solve this problem perfectly.
class Thread(QThread):
Book: Create Desktop Apps with Python PyQt5
QProgressBar example
This example uses the time module in python to do the delay operation time.sleep()
.
It puts the delay operation into the sub-thread to realize the real-time UI refresh of PyQt.
Because the thread is doing the QProgressBar update, it doesn’t cause the main thread to hang.
import sys
import time
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QPushButton, QProgressBar, QVBoxLayout, QApplication
class Thread(QThread):
_signal = pyqtSignal(int)
def __init__(self):
super(Thread, self).__init__()
def __del__(self):
self.wait()
def run(self):
for i in range(100):
time.sleep(0.1)
self._signal.emit(i)
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.setWindowTitle('QProgressBar')
self.btn = QPushButton('Click me')
self.btn.clicked.connect(self.btnFunc)
self.pbar = QProgressBar(self)
self.pbar.setValue(0)
self.resize(300, 100)
self.vbox = QVBoxLayout()
self.vbox.addWidget(self.pbar)
self.vbox.addWidget(self.btn)
self.setLayout(self.vbox)
self.show()
def btnFunc(self):
self.thread = Thread()
self.thread._signal.connect(self.signal_accept)
self.thread.start()
self.btn.setEnabled(False)
def signal_accept(self, msg):
self.pbar.setValue(int(msg))
if self.pbar.value() == 99:
self.pbar.setValue(0)
self.btn.setEnabled(True)
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
Progressbar styles
The example below uses CSS stylesheet to make variations of the QProgressBar.
from random import randint
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QProgressBar
StyleSheet = '''
#RedProgressBar {
text-align: center;
}
#RedProgressBar::chunk {
background-color: #F44336;
}
#GreenProgressBar {
min-height: 12px;
max-height: 12px;
border-radius: 6px;
}
#GreenProgressBar::chunk {
border-radius: 6px;
background-color: #009688;
}
#BlueProgressBar {
border: 2px solid #2196F3;
border-radius: 5px;
background-color: #E0E0E0;
}
#BlueProgressBar::chunk {
background-color: #2196F3;
width: 10px;
margin: 0.5px;
}
'''
class ProgressBar(QProgressBar):
def __init__(self, *args, **kwargs):
super(ProgressBar, self).__init__(*args, **kwargs)
self.setValue(0)
if self.minimum() != self.maximum():
self.timer = QTimer(self, timeout=self.onTimeout)
self.timer.start(randint(1, 3) * 1000)
def onTimeout(self):
if self.value() >= 100:
self.timer.stop()
self.timer.deleteLater()
del self.timer
return
self.setValue(self.value() + 1)
class Window(QWidget):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.resize(800, 600)
layout = QVBoxLayout(self)
layout.addWidget(
ProgressBar(self, minimum=0, maximum=100, objectName="RedProgressBar"))
layout.addWidget(
ProgressBar(self, minimum=0, maximum=0, objectName="RedProgressBar"))
layout.addWidget(
ProgressBar(self, minimum=0, maximum=100, textVisible=False,
objectName="GreenProgressBar"))
layout.addWidget(
ProgressBar(self, minimum=0, maximum=0, textVisible=False,
objectName="GreenProgressBar"))
layout.addWidget(
ProgressBar(self, minimum=0, maximum=100, textVisible=False,
objectName="BlueProgressBar"))
layout.addWidget(
ProgressBar(self, minimum=0, maximum=0, textVisible=False,
objectName="BlueProgressBar"))
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyleSheet(StyleSheet)
w = Window()
w.show()
sys.exit(app.exec_())
When creating progressbars, we use the parameter objectName to set the css class name.
layout.addWidget(
ProgressBar(self, minimum=0, maximum=0, objectName="RedProgressBar"))
layout.addWidget(
ProgressBar(self, minimum=0, maximum=0, textVisible=False,
objectName="GreenProgressBar"))
layout.addWidget(
ProgressBar(self, minimum=0, maximum=0, textVisible=False,
objectName="BlueProgressBar"))
You can see they match the styleSheets class names (on top):
#RedProgressBar {
...
#GreenProgressBar {
...
#BlueProgressBar {
...