QPushButton QPropertyAnimation QThread

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Omm
User
Beiträge: 90
Registriert: Samstag 7. April 2018, 14:05

Hallo zusammen
Meine Kernfrage ist:
Wie kann ich eine Animation von einem Pushbutton über einen Thread starten?

Mein Endziel ist es. dass z.b. jeden Tag um 12:00Uhr dieser Butten(Mittag) mit Blinken anfängt. Sobald ein Button angeklickt wird, soll die Animation beendet werden.

Leider habe ich keine Plan wo ich anfangen soll. Die Animation über einen anderen Button konnte ich im Netz finden.
Ich stelle mir das so vor: Thread schaut ob es 12:00 Uhr ist. Dieser startet dann das Blinke. Das Blinken wird erste beendet nach einem Click auf einen Button oder nach 10min.

Mit einem normalen Blinken konnte ich schon lösen, jedoch möchte ich es animiert haben und wenn möglich mit Qt.

Code: Alles auswählen

class WindowProjektEintragen(QWidget):
    ADDDELTATIME_AB_ALARLTIME = datetime.timedelta(hours=0, minutes=10).total_seconds()  # Dauer des blinken.
    STATUS_BLINKI = True

    def __init__(self, *args, **kwargs):
        super(WindowProjektEintragen, self).__init__(*args, **kwargs)
    
        # create schedule
        self.stopBlinking = threading.Event()
        self.quitThread = threading.Event()
        schedule_thread = threading.Thread(name='Scheduling-Thread', target=self.run_schedule_thread)
        schedule_thread.start()

    def run_schedule_thread(self):
        """ run in a separate thread. """
        start_blinkten = settings.getStrValue('START_BLINKZEIT')     # z.b. START_BLINKZEIT = 12:00 aus der settings.ini Datei
        schedule.every().day.at(start_blinkten).do(self.popupmeldung_mittag)
        while not self.quitThread.isSet():
            schedule.run_pending()
            time.sleep(2)

    def popupmeldung_mittag(self):
        color_button = self.palette().color(QPalette.Midlight).getRgb()
        color_highlight = self.palette().color(QPalette.Highlight).getRgb()
        end_time = (time.time() + self.ADDDELTATIME_AB_ALARLTIME)
        while (time.time() < end_time and self.get_status_blinki()) and not self.quitThread.isSet():
            time.sleep(0.5)
            self.b_Mittag.setStyleSheet("background-color: rgb({0}, {1}, {2});".format(color_highlight[0], color_highlight[1], color_highlight[2]))
            time.sleep(0.5)
            self.b_Mittag.setStyleSheet("background-color: rgb({0}, {1}, {2});".format(color_button[0], color_button[1], color_button[2]))
        self.stopBlinking.clear()

    def get_status_blinki(self):
        return self.STATUS_BLINKI

Ich hoffe ich konnte als Anfänger, einigermassen erläutern was mein Endziel ist.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Threads und GUIs vertragen sich nicht. Wenn Qt und Threads, dann benutzt man QThreads und nicht threading. Hier würde ich aber mit einem QTimer arbeiten.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich würde gleich zu dem Animations-Framework greifen, das mit Qt mitkommt. https://doc.qt.io/qt-5/animation-overview.html
Omm
User
Beiträge: 90
Registriert: Samstag 7. April 2018, 14:05

__deets__ hat geschrieben: Dienstag 22. Dezember 2020, 10:18 Ich würde gleich zu dem Animations-Framework greifen, das mit Qt mitkommt. https://doc.qt.io/qt-5/animation-overview.html
Danke für deine Antwort.
ich denke mir fehlt eine Schlüsselinfo.
als Beispiel:

Code: Alles auswählen

class BlinkButton(QPushButton):
    def __init__(self, *args, **kwargs):
        super(BlinkButton, self).__init__(*args, **kwargs)
        effect = QGraphicsColorizeEffect(self)
        self.setGraphicsEffect(effect)
        self.animation = QtCore.QPropertyAnimation(effect, b"color")
        self.animation.setLoopCount(5)
        self.animation.setDuration(900)
        self.animation.setStartValue(QColor(QtCore.Qt.red))
        self.animation.setEndValue(QColor(QtCore.Qt.darkGreen))
        self.animation.start()
wie kann ich den BlinkButton, aus einem QThread, ausstarten und stoppen . Ein loop mit time.sleep oder ein QThread das permanent läuft führt dazu, dass die Animation gestoppt wird.
Irgendwie fehlt mir die Struktur(das Basis wissen), wie sowas gemacht werden kann.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Omm: wie ich schon schrieb, würde ich hierfür keinen Thread benutzen, sondern einen QTimer.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn du etwas in Qt aktivieren willst, dann ist dazu der signal/slot-Mechanismus gedacht. Du kannst in deinem BlinkButton die Slots blinkStart und blinkStop anlegen, und aus anderen Objekten heraus aufrufen, zB von einem von Sirius benannten QTimer.

QThreads wuerde ich an deiner Stelle vergessen, denn Programmierung mit Threads ist *schwer*, und hat viele dem Anfaenger unbekannte Nebenwirkungen.
Omm
User
Beiträge: 90
Registriert: Samstag 7. April 2018, 14:05

Hallo zusammen

vielen Dank für eure Hilfe.
QTimer scheint wirklich die Zauberloesung zu sein.
zu Testzwecken habe ich dies mal so geloest:

Code: Alles auswählen

class BlinkButton(QPushButton):
    def __init__(self, *args, **kwargs):
        super(BlinkButton, self).__init__(*args, **kwargs)
        QPushButton.__init__(self, *args, **kwargs)

        self.timer = QTimer()

        effect = QGraphicsColorizeEffect(self)
        self.setGraphicsEffect(effect)
        self.animation = QtCore.QPropertyAnimation(effect, b"color")
        self.animation.setLoopCount(1)
        self.animation.setDuration(900)
        self.animation.setStartValue(QColor(QtCore.Qt.red))
        self.animation.setEndValue(QColor(QtCore.Qt.darkGreen))
        print('a')

    def blinkStart(self):
        self.timer.start(1000)
        self.timer.timeout.connect(self.animation.start)
        print('b')

    def blinkStop(self):
        self.timer.stop()
        print('c')


class Widget(QWidget):
    def __init__(self):
        super(Widget, self).__init__()
        self.resize(300,200)
        layout = QVBoxLayout(self)

        self.button_Mittag = BlinkButton("Mittag")
        layout.addWidget(self.button_Mittag)
        self.button_Mittag.clicked.connect(self.stop)

        self.button_Mittag.blinkStart()

    def stop(self):
        self.button_Mittag.blinkStop()


if __name__ == "__main__":
    app = QApplication([])
    w = Widget()
    w.show()
    app.exec_()

so kann ich nun den timer starten oder stoppen. :D
nochmals Vielen herzlichen Dank euch beiden für die Hilfe.
Antworten