Seite 1 von 1

code revue

Verfasst: Freitag 1. Januar 2021, 15:34
von Omm
Hallo zusammen

kann mir jemand sagen, wieso die Printausgabe zwei mal was ausgibt.
Ich habe den Eindruck, dass die Animation doppelt gestartet wird. Genau so wie die Printausgabe

Code: Alles auswählen


class AnimButton(QPushButton):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.thread = WorkerThread(self)
        self.thread.start()
        self.thread.animation.connect(self.check_animation)

        color_button = self.palette().color(QPalette.Button).getRgb()
        color_highlight = self.palette().color(QPalette.Highlight).getRgb()
        self.timer = QTimer()
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.animieren)
        self.color_flag = True

        self.color1 = QtGui.QColor(color_button[0], color_button[1], color_button[2])
        self.color2 = QtGui.QColor(color_highlight[0], color_highlight[1], color_highlight[2])

        self._animation = QtCore.QVariantAnimation(
            self,
            valueChanged=self._animate,
            startValue=0.00001,
            endValue=0.9999,
            duration=500
        )

    def check_animation(self):
        while self.animieren():
            self.timer.start()
        self.timer.stop()
        self.setStyleSheet('')

    def _animate(self, value):
        grad = "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop:{value} {color2}, stop: 1.0 {color1});".format(
            color1=self.color1.name(), color2=self.color2.name(), value=value
        )
        self.setStyleSheet(grad)

    def animieren(self):
        if self.color_flag:
            self._animation.setDirection(QtCore.QAbstractAnimation.Forward)
            self._animation.start()
        else:
            self._animation.setDirection(QtCore.QAbstractAnimation.Backward)
            self._animation.start()
        self.color_flag = not self.color_flag


class WorkerThread(QThread):
    animation = pyqtSignal(bool)

    def __init__(self, parent=None):
        super(WorkerThread, self).__init__(parent)
        self._running = False
        self.animation.emit(False)
        self.animation_flag = False
        self.test = 0

    def run(self):
        self._running = True
        while self._running:
            self.doWork()

    def doWork(self):
        interval = 5000
        loop = QEventLoop()
        QTimer.singleShot(interval, loop.quit)
        loop.exec_()
        self.check_time()
        print(self.test)
        self.test += 1

    def check_time(self):
        zeit_start_animation = QTime.fromString("15:28", "hh:mm")
        zeit_stop_animation = zeit_start_animation.addSecs(30)
        now = QDateTime.currentDateTime().time()

        if now > zeit_start_animation and now < zeit_stop_animation:
            self.animation.emit(True)


Re: code revue

Verfasst: Freitag 1. Januar 2021, 22:16
von Omm
ich habe es ein wenig angepasst.
Die doppelausgabe bei print('d') bleibt.
Auch wenn es funktioniert, wüsste ich gerne wieso dies so ist.

Code: Alles auswählen

class AnimButton(QPushButton):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.color_flag = True
        self.worker = WorkerThread()
        self.worker.status.connect(self.handle_connection)
        self.worker.start()

        self.timer = QTimer()
        self.timer.setInterval(800)
        self.timer.timeout.connect(self.animieren)

        color_button = self.palette().color(QPalette.Button).getRgb()
        color_highlight = self.palette().color(QPalette.Highlight).getRgb()
        self.color1 = QtGui.QColor(color_button[0], color_button[1], color_button[2])
        self.color2 = QtGui.QColor(color_highlight[0], color_highlight[1], color_highlight[2])

        self._animation = QtCore.QVariantAnimation(self, valueChanged=self._animate, startValue=0.00001, endValue=0.9999, duration=500)
        self.setStyleSheet('')

    def handle_connection(self, status_blinken):
        if status_blinken:
            self.timer.start()
        else:
            self.timer.stop()
            self.setStyleSheet('')

    def _animate(self, value):
        grad = "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop:{value} {color2}, stop: 1.0 {color1});".format(
            color1=self.color1.name(), color2=self.color2.name(), value=value)
        self.setStyleSheet(grad)

    def animieren(self):
        if self.color_flag:
            self._animation.setDirection(QtCore.QAbstractAnimation.Forward)
            self._animation.start()
        else:
            self._animation.setDirection(QtCore.QAbstractAnimation.Backward)
            self._animation.start()
        self.color_flag = not self.color_flag


class WorkerThread(QThread):
    status = pyqtSignal(bool)
    oneParameterSignal = pyqtSignal(str)

    def __init__(self, parent=None):
        super(WorkerThread, self).__init__(parent)
        self.running = False
        self.test = 0

    def run(self):
        self._running = True
        while self._running:
            time.sleep(5)
            self.check_time()

    def check_time(self):
        print('d')
        zeit_start_animation = QTime.fromString("22:12", "hh:mm")
        zeit_stop_animation = zeit_start_animation.addSecs(300)
        now = QDateTime.currentDateTime().time()
        if now > zeit_start_animation and now < zeit_stop_animation:
            self.status.emit(True)
        else:
            self.status.emit(False)


Re: code revue

Verfasst: Samstag 2. Januar 2021, 14:30
von __deets__
Der Thread ist komplett ueberfluessig. Dafuer reicht ein normaler Timer. Dan self._animation.start() kommt in jedem if/else-Zweig vor. Kann also *einmal* dahinter. check_time wird alle 5 Sekunden aufgerufen. Wie oft das print also passiert haengt davon ab, wie lange dein Programm laeuft.

Und zu guter Letzt: man laesst Code Revue passieren, aber man bittet um ein Code Review.

Re: code revue

Verfasst: Samstag 2. Januar 2021, 20:24
von Omm
__deets__
danke für deine Antwort.
Ja hast recht, QThread ist echt überflüssig. Ich werde es umbauen.
Meine Frage ging dahingehend, dass (print'd') immer zwei mal gleichzeitig ausgegeben wird. D.h. alle 5s kommen zwei 'd' raus. Natürlich solange das Programm läuft.
Mir ist nicht klar, ob dieser Effekt nur bei mir ist, oder das Verhalten so normal ist. Ersteres dürfte eher zutreffen.

Re: code revue

Verfasst: Samstag 2. Januar 2021, 20:34
von __deets__
Ohne ein geschlossenes, nachvollziehbares Beispiel ist das schwer zu sagen. Allgemein laufen Threads selbstverstaendlich nur einmal. Nicht mehrfach. Es ist also irgendetwas in deinem Code.

Das von dir verwandte Muster, Threads per Ableitung zu nutzen, wird uebrigens sehr explizit *nicht* mehr empfohlen. https://doc.qt.io/qt-5/qthread.html#details

Man sollte Worker-Objekte mit moveToThread benutzen, damit signal/slot-connections sauber funktionieren.

Ich wuerde das Thema Threads aber auch nur angehen, wenn du *musst*. Denn das ist komplex. Und bisher musst du nicht.