Created
October 25, 2020 13:57
-
-
Save cedricduriau/52472eaa70e4362dfa16703abaa3be8b to your computer and use it in GitHub Desktop.
CLI/GUI Progress Bar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# stdlib modules | |
import sys | |
import time | |
# third party modules | |
from PySide2 import QtCore, QtWidgets | |
class AbstractProgressBar(QtCore.QObject): | |
# signals | |
start_changed = QtCore.Signal(int) | |
end_changed = QtCore.Signal(int) | |
step_changed = QtCore.Signal(int) | |
value_changed = QtCore.Signal(int) | |
title_changed = QtCore.Signal(str) | |
message_changed = QtCore.Signal(str) | |
def __init__(self): | |
super(AbstractProgressBar, self).__init__() | |
self._start = 0 | |
self._end = 1 | |
self._step = 1 | |
self._value = 0 | |
self._title = "" | |
self._message = "" | |
@property | |
def start(self): | |
return self._start | |
@start.setter | |
def start(self, value): | |
self._start = value | |
self.start_changed.emit(value) | |
@property | |
def end(self): | |
return self._end | |
@end.setter | |
def end(self, value): | |
self._end = value | |
self.end_changed.emit(value) | |
@property | |
def step(self): | |
return self._step | |
@step.setter | |
def step(self, value): | |
self._step = value | |
self.step_changed.emit(value) | |
@property | |
def value(self): | |
return self._value | |
@value.setter | |
def value(self, value): | |
self._value = value | |
self.value_changed.emit(value) | |
@property | |
def title(self): | |
return self._title | |
@title.setter | |
def title(self, value): | |
self._title = value | |
self.title_changed.emit(value) | |
@property | |
def message(self): | |
return self._message | |
@message.setter | |
def message(self, value): | |
self._message = value | |
self.message_changed.emit(value) | |
def advance(self): | |
self.value = self.value + self.step | |
class ProgressBarCLI(AbstractProgressBar): | |
def __init__(self): | |
super(ProgressBarCLI, self).__init__() | |
self.width = 10 | |
self.char_fill = "#" | |
self.char_empty = " " | |
self._previous_line = "" | |
self.value_changed.connect(self._print_value) | |
@property | |
def width(self): | |
return self._width | |
@width.setter | |
def width(self, value): | |
self._width = value | |
def _print_value(self, value): | |
if self._previous_line: | |
sys.stdout.write(len(self._previous_line) * " " + "\r") | |
sys.stdout.flush() | |
step = (self.width / self.end) * self.step | |
value = int(self.value * step) | |
fill_str = value * self.char_fill | |
empty_str = (self.width - len(fill_str)) * self.char_empty | |
bar = "{} {} [{}{}]".format(self.title, self.message, fill_str, empty_str) | |
# store previous | |
self._previous_line = bar | |
bar += "\r" | |
if self.value >= self.end: | |
bar += "\n" | |
sys.stdout.write(bar) | |
sys.stdout.flush() | |
class ProgressBarGUI(QtWidgets.QWidget): | |
def __init__(self, pbar): | |
self._pbar = pbar | |
super(ProgressBarGUI, self).__init__() | |
self._build_ui() | |
self._connect_signals() | |
self._refresh() | |
def _build_ui(self): | |
self._title = QtWidgets.QLabel() | |
self._message = QtWidgets.QLabel() | |
self._pbar_widget = QtWidgets.QProgressBar() | |
self.setLayout(QtWidgets.QHBoxLayout()) | |
self.layout().addWidget(self._title) | |
self.layout().addWidget(self._message) | |
self.layout().addWidget(self._pbar_widget) | |
def _connect_signals(self): | |
self._pbar.title_changed.connect(self._title.setText) | |
self._pbar.message_changed.connect(self._message.setText) | |
self._pbar.start_changed.connect(self._pbar_widget.setMinimum) | |
self._pbar.end_changed.connect(self._pbar_widget.setMaximum) | |
self._pbar.value_changed.connect(self._pbar_widget.setValue) | |
self._pbar.start_changed.connect(self._refresh) | |
self._pbar.end_changed.connect(self._refresh) | |
self._pbar.value_changed.connect(self._refresh) | |
def _refresh(self, *args, **kwargs): | |
QtCore.QCoreApplication.processEvents() | |
if __name__ == "__main__": | |
# cli | |
pbar = ProgressBarCLI() | |
# gui | |
app = QtWidgets.QApplication.instance() or QtWidgets.QApplication() | |
widget = ProgressBarGUI(pbar) | |
dialog = QtWidgets.QDialog() | |
dialog.setLayout(QtWidgets.QVBoxLayout()) | |
dialog.layout().addWidget(widget) | |
dialog.show() | |
# action iterable | |
l = list(range(10)) | |
# settings | |
pbar.title = "iteration:" | |
pbar.end = len(l) | |
pbar.width = 20 | |
for i in l: | |
pbar.message = str(i + 1) | |
time.sleep(0.5) # action | |
pbar.advance() | |
sys.exit(dialog.exec_()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment