Servus,
ich bin gerade dabei, meinen >> Mediaplayer für Python3 << zu verbessern/erweitern.
mein Problem:
Auch jetzt kann man schon in der derzeit auf Github aktuellen Version 0.1 (Github-Repository >> hier <<) einstellen, mit welchem Alpha-Wert (Transparenz) ein Video dargestellt werden soll. Dieser Wert wird über das tkinter-Widget Spinbox eingestellt. Jetzt wird der Alpha-Wert beim Aufruf von omxplayer.bin als Kommandozeilenparameter übergeben und kann während des Abspielens nicht verändert werden. Zwischenzeitliche Änderungen wirken sich also erst bei einem Neustart von omxplayer.bin aus, d.h. beim Start des nächsten Videos.
Eine geplante Verbesserung soll sein, dass ein geänderter Alpha-Wert über ein dbus-Kommando "sofort" an omxplayer.bin gesendet wird und das Video sofort in seiner Transparenz geändert wird. Die in meinem Programm verwendete Python-Klasse >> github.com/willprice/python-omxplayer-wrapper << gibt eine entsprechende Funktion set_alpha(alpha) her und das funktioniert auch.
Für die Einstellung des Alpha-Wertes (0 - 255 in 15er-Schritten) verwende ich das tkinter-Widget Spinbox, das eigentlich für so etwas vorgesehen ist. Die Instanz des Widgets wird so erstellt:
[code=php]self.spinAlpha = tkinter.Spinbox(self.frPlayerbuttons, width = 4, from_ = 0, to = 255, increment = 15, font = self.fileFont) # width = Anzahl der dargestellten Zeichen
[/php]
und so werden die Ereignishandler gebunden:
[code=php]self.spinAlpha.bind('<KeyRelease>', self.spinAlpha_KeyRelease) # 2016-11-20 schlizbaeda V0.2: Ereignis für Änderung des Alpha-Wertes (Transparenz)
self.spinAlpha.bind('<ButtonRelease-1>', self.spinAlpha_Click) # 2016-11-20 schlizbaeda V0.2: Ereignis für Änderung des Alpha-Wertes (Transparenz)
[/php]
Zunächst wurde der erste Ereignishandler für das Tastaturereignis erstellt:
[code=php]
def spinAlpha_KeyRelease(self, event):
# 2016-11-20 schlizbaeda V0.2: Ereignishandler für Änderung des Alpha-Wertes (Transparenz) über die Tastatur (Loslassen): Zu diesem Zeitpunkt ist der Textinhalt des Steuerelementes bereits aktualisiert!
alpha = self.spinAlpha.get()
if alpha == '': alpha = '0'
try:
alpha = int(alpha)
except:
alpha = self.gl_alphaDefault
if alpha > 255:
alpha = 255
elif alpha < 0:
alpha = 0
# Das Setzen des Alpha-Wertes (Transparenz) ist nur bei Videos möglich. Audiodateien werfen eine Exception --> daher try/except
try:
self.gl_omxplayer.set_alpha(alpha) # Alpha-Wert (Transparenz) über dbus ändern
except:
pass
[/php]
Hier wird der aktuelle Wert des Spinbox-Widgets ausgelesen und per dbus an omxplayer.bin gesendet. Es ist der Wert, der NACH der Änderung im Widget steht. Wenn z.B. mit "Cursor-down" von 201 auf 195 geändert wird, liest self.spinAlpha.get() wie erwartet, den Wert 195, den man als Anwender an dieser Stelle intuitiv erwartet.
Nicht jedoch beim Ereignishandler für <ButtonRelease-1>:
[code=php]
def spinAlpha_Click(self, event):
# 2016-11-20 schlizbaeda V0.2: Ereignishandler für Änderung des Alpha-Wertes (Transparenz) über ein Klick-Ereignis: Zu diesem Zeitpunkt ist der Textinhalt des Steuerelementes NOCH NICHT aktualisiert!
## Alle im folgenden auskommentierten Anweisungen beißen nicht wie gewünscht an:
## Der Wert der über self.spinAlpha.get() ausgelesen wird, wird offenbar erst
## NACH der vollständigen Abarbeitung des Ereignishandlers aktualisiert,
## d.h. während der Abarbeitung erhält man noch den alten Wert!
#self.YAMuPlayGUI.update() # DoEvents
#time.sleep(1.5)
#self.YAMuPlayGUI.after(2000, self.spinAlpha_KeyRelease(event)) # funzt nicht!
self.spinAlpha_KeyRelease(event)
print(self.spinAlpha.get()) # DEBUG!
[/php]
Hier wird der Wert des Spinbox-Widgets ausgelesen, der UNMITTELBAR VOR der Änderung im Widget steht. Wenn z.B. mit "Cursor-down" von 201 auf 195 geändert wird, liest self.spinAlpha.get() den Wert 210 und unmittelbar danach wird der Wert erst aktualisiert. Die Folge ist, dass die Transparenz des Videos dann nicht dem angezeigten Wert im Widget entspricht!
Die ganzen Befehle, mit denen ich herumprobiert habe, sind auskommentiert, da sie keine Änderung bewirken.
Mir ist schon klar, dass die Ereignisverwaltung einer GUI beim Auftreten eines Ereignisses irgendwelche internen Sachen abarbeiten muss und erste den KOMPLETTEN Ereignishandler abarbeiten muss, bevor sie wieder in die Mainloop zurückkehrt. Beim Button-Ereignis, selbst in der ButtonRelease-Variante wird vermutlich zuerst der gebundene Ereignishandler abgearbeitet und erst danach das Unterereignis für die kleinen Pfeil-Buttons im Spinbox-Widget. So erklärt sich für mich die verspätete Aktualisierung des Wertes.
Beim KeyRelease-Ereignis ist es offenbar andersherum und der im Ereignishandler ermittelte Wert ist "richtig".
Was ich an dieser Stelle komisch finde und nicht verstehe:
Warum beißt hier self.YAMuPlayGUI.after(2000, self.spinAlpha_KeyRelease(event)) nicht an? Die Wirkung ist die gleiche wie bei time.sleep(1.5): Es verlängert nur die Ausführungszeit des Ereignishandlers. Wegen der langen Testzeiten sieht man in der GUI genau, dass die Werte im Spinbox-Widget erst danach aktualisiert werden. Ich dachte immer, after dient in Python/tkinter dazu, der mainloop mitzuteilen, den angegebenen Befehl erst einige Millisekunden später aus der mainloop heraus auszuführen. Dann müsste ja der Ereignishandler "sofort" mit dem nächsten Befehl fortfaren und noch vor dem Kommando aus der after-Anweisung beendet sein (inkl. aller internen Ereignishandler für die Pfeilbuttons etc).
Oder liege ich hier völlig falsch und verstehe die richtige Arbeitsweise von after nicht?