Skip to content

Instantly share code, notes, and snippets.

@cedricduriau
Created October 25, 2020 13:57
Show Gist options
  • Save cedricduriau/52472eaa70e4362dfa16703abaa3be8b to your computer and use it in GitHub Desktop.
Save cedricduriau/52472eaa70e4362dfa16703abaa3be8b to your computer and use it in GitHub Desktop.
CLI/GUI Progress Bar
# 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