class ProgressDialog(QDialog): _default = ''' QProgressBar { min-width: 350px; } ''' def __init__(self, parent, title, total_progress): super().__init__(parent) self.setWindowTitle(title) self._total_progress = total_progress self._progress_bar = None self._setup_ui() self._prepare() def _setup_ui(self): self.setStyleSheet(self._default) self.setWindowFlags( Qt.Window | Qt.WindowTitleHint | Qt.CustomizeWindowHint ) self.setStyleSheet(self._default) layout = make_layout( horizon=False, margin=24, spacing=24 ) self._progress_bar = QProgressBar() self._progress_bar.setRange(0, self._total_progress) self._progress_bar.setTextVisible(True) self._progress_bar.setFormat(r'%p% (%v/%m)') self._progress_bar.setValue(0) layout.addWidget( self._progress_bar ) self.setLayout(layout) move_center(self) def _prepare(self): return def increase(self, step=1): self._progress_bar.setValue(self._progress_bar.value() + step) if self._progress_bar.value() == self._progress_bar.maximum(): self.close() def _on_show(self): return def _on_close(self): return def showEvent(self, event): self._on_show() event.accept() def closeEvent(self, event): self._on_close() event.accept()
class SplashScreen(QSplashScreen): """ Display a Splashscreen """ signal_done = QtCore.pyqtSignal() def __init__(self): QSplashScreen.__init__(self, QtGui.QPixmap(), QtCore.Qt.WindowStaysOnTopHint) self.rootDir = Path(__file__).parent # default values self.image = None self.version = "Version: 3.x" # pixmap.height - ? self.progress_y = 68 # pixmap.width - ? self.vx = 24 # pixmap.height - ? self.vy = 32 # message font size self.msize = 12 self.cv = OpenCVLib() self.progressBar = QProgressBar(self) self.progressBar.setMinimum(0) self.progressBar.setValue(0) self.progressBar.setMaximum(100) self.progressBar.setTextVisible(False) self.setPositionProgressBar() self.message = QLabel(self) self.message.setFont(QFont("Arial", self.msize)) self.message.setStyleSheet("QLabel { color : #000000; }") self.message.setAlignment(Qt.AlignCenter) # Shadow Effekt effect = QGraphicsDropShadowEffect(self) effect.setBlurRadius(5) effect.setColor(QColor("#ffffff")) effect.setOffset(1, 1) self.message.setGraphicsEffect(effect) self.setPositionMessage() # self.message.hide() # CSS Styling self.setStyleSheet(""" QProgressBar{ border: 1px solid #eeeeee; text-align: center; padding: 0; margin-top: 10px; } QProgressBar::chunk{ background-color: #3daee9; width: 0.34em; margin: 0 1px; } """) def show(self, *args, **kwargs): if self.image == None: raise ValueError('Specify an Image via SplashScreen::setImage()') return QSplashScreen.show(self, *args, **kwargs) def setMessage(self, msg): self.message.setText("%s ..." % (msg)) self.message.show() def setPositionMessage(self): """ place Message on screen """ # where is progress? p = self.progressBar.geometry() self.message.setGeometry(0, p.y() - self.msize, self.pixmap().width(), 2 * self.msize) self.message.updateGeometry() def setPositionProgressBar(self): """ place ProgressBar on screen """ margin = 10 # x, y, w, h self.progressBar.setGeometry(margin, self.pixmap().height() - self.progress_y, self.pixmap().width() - 2 * margin, 20) self.progressBar.updateGeometry() def scale(self, pix): gold = 0.618 h = pix.size().height() w = pix.size().width() # max width 68% of screen screen = QGuiApplication.screens()[0] new_w = screen.geometry().width() * gold new_h = h * new_w / w # python resize # return pix.scaled(new_w, new_h, Qt.KeepAspectRatioByExpanding | Qt.SmoothTransformation) # resize with opencv Qimg = pix.toImage() img = self.cv.QImage2MAT(Qimg) resized = self.cv.resizeTo(img, new_w, new_h) return self.cv.MAT2QPixmap(resized) def setVersion(self, version): """ adds a Version Number and updates the image """ self.version = "Version: %s" % version def paintEvent(self, *args, **kwargs): """ override, important to work """ return QSplashScreen.paintEvent(self, *args, **kwargs) def setImage(self, img): """ sets the image and adds a Version Number """ self.image = self.rootDir.joinpath(img).as_posix() splash_pix = QtGui.QPixmap(self.image, format='jpg') if splash_pix.isNull(): raise ValueError('Error loading Image [self.image]') # Add version painter = QtGui.QPainter(splash_pix) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setFont(QFont("Arial", 18)) painter.setPen(QColor("#666666")) painter.drawText(0, 0, splash_pix.size().width() - self.vx, splash_pix.size().height() - self.vy, QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight, self.version) painter.end() self.setPixmap(self.scale(splash_pix)) # ---------------------------------------------- # other stuff self.setPositionProgressBar() self.setPositionMessage() def step(self): """ a preloading step is done """ self.progressBar.setValue(self.progressBar.value() + 1) self.progressBar.repaint() if (self.progressBar.value() >= (self.progressBar.maximum() - 1)): self.signal_done.emit() def setProgressMax(self, maxval): self.progressBar.setMaximum(maxval)
class ProgressBar(QDialog): def __init__(self, __images_dir, parent=None): QDialog.__init__(self, parent=parent) self.__thread = None # l'objet QThread qui fera le calcul self.__images_dir = __images_dir # le dossier des images self.__images_list = None # la liste des images *.png à traiter self.__vMin = None # la valeur min de la barre self.__vMax = None # la valeur max de la barre self.title = QLabel("",self) self.pbar = QProgressBar(self) self.pbar.setGeometry(30, 40, 250, 25) self.btnOk = QPushButton('OK', self) self.btnOk.clicked.connect(self.close) self.btnOk.setEnabled(False) self.btnCancel = QPushButton('Cancel', self) self.btnCancel.clicked.connect(self.Cancel) self.btnCancel.setEnabled(True) vbox = QVBoxLayout() vbox.addWidget(self.title) vbox.addWidget(self.pbar) hbox = QHBoxLayout() hbox.addWidget(self.btnOk) hbox.addWidget(self.btnCancel) vbox.addLayout(hbox) self.setLayout(vbox) self.setModal(True) self.setWindowModality(Qt.ApplicationModal) self.show() def configure_for_video_extraction(self, videoCapture, imagesFormat): self.__vMin = 1 self.__vMax = int(videoCapture.get(cv2.CAP_PROP_FRAME_COUNT)) self.pbar.setRange(self.__vMin, self.__vMax) self.pbar.setValue(self.__vMin) self.setWindowTitle('Découpage de la vidéo') self.title.setText("Extraction images : ") self.__thread = SplitVideoInImagesThread(videoCapture, self.__images_dir, imagesFormat) self.__thread.ImageExtractedSig.connect(self.updateProgressBar) self.__thread.ImageProblemSig.connect(self.updateProgressBar) self.__thread.start() def configure_for_target_extraction(self, target_RGB, algo, marge_couleur, target_pos, first_last_step): self.__images_list = [ f for f in os.listdir(self.__images_dir) if f.endswith(".png")] self.__images_list.sort() self.__vMin, self.__vMax, _ = first_last_step self.pbar.setRange(self.__vMin, self.__vMax) self.pbar.setValue(self.__vMin) self.setWindowTitle('Traitement des images du dossier {}'\ .format(self.__images_dir)) # Lancer un __thread pour le travil d'extraction des images de la vidéo : self.__thread = ExtractTargetFomImagesThread(self.__images_dir, self.__images_list, target_RGB, algo, marge_couleur, target_pos, first_last_step) self.__thread.TargetExtractedSig.connect(self.updateProgressBar) self.__thread.TargetProblemSig.connect(self.updateProgressBar) self.__thread.start() def Cancel(self): # Appui sur le bouton Cancel. # Arrêter le Thread en cours : self.__thread.quit() # Fermer la fenêtre QDialog avec un code retour à -1 : self.done(-1) def updateProgressBar(self, value): if value >= 0: # l'image N° <value> vient d'être traitée avec succès : self.pbar.setValue(value) self.btnOk.setEnabled(True) if value == 0 or value == self.pbar.maximum(): self.btnOk.setEnabled(True) mess = "{:3d}/{:3d}".format(value,self.__vMax) else: # l'image N° <value> a provoqué une erreur : mess = self.title.text() mess += '\n Erreur image {}'.format(-value) self.title.setText("Extraction images : " + mess)