Seite 1 von 2

Nach 5min Inaktiv Bild anzeigen

Verfasst: Sonntag 23. November 2014, 21:21
von schnibli
Hallo zusammen,
Ich würde gerne, wenn 5 Minuten nichts geklickt wird auf dem Touchscreen, auf diesem ein Bild anzeigen lassen.
Ich kann dies nicht über den Screensaver machen da ich diesen nach weitern 5 Minuten aktivieren möchte :)

Kann mir jemand helfen?

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Montag 24. November 2014, 07:29
von Michael Schneider
Spricht etwas gegen eine eigene Zeitzählschleife?
Du definierst eine Variable z.B. last_action_time, die jeweils bei Interaktion die aktuelle Zeit time.time speichert.
Außerdem eine Methode last_action_time_checker, die die Differenz zwischen time.time und last_action_time ermittelt, sofern letztere nicht gleich 0 ist.
Ist die Differenz größer als ein Grenzwert, 300s bei 5 Minuten, führ die Aktion aus und setz last_action_time auf 0. Am Ende registriert sich die Methode selbst für erneute Ausführung mit self.after(...) nach n Millisekunden, je nach Prüfintervall.

Ich merke gerade, ein paar Zeilen Code wären kürzer gewesen. :lol:

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Montag 24. November 2014, 10:12
von schnibli
Hallo, ich weis genau was du meinst.
Jedoch habe ich Probleme dies Umzusetzen.

Meinst du das ich bei jedem Button klick
last_action_time = 0 setzten muss?

Wie kann ich wie löse ich das mit dem Timer :) ...

Danke für dein Verständnis und deine Geduld :)

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Montag 24. November 2014, 10:34
von Michael Schneider
Hi schnibli,
schnibli hat geschrieben:Meinst du das ich bei jedem Button klick
last_action_time = 0 setzten muss?

Wie kann ich wie löse ich das mit dem Timer :)
ich habe hier leider kein python installiert, darum kann ich den Code nicht testen. Aber ich meine das in etwa so (nur für das Problem wichtiger Code):

Code: Alles auswählen

import Tkinter as tk
import time

class MainWindow(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.last_action_time = 0
        self.last_action_time_poll_interval = 1000  # 1000 ms min. Zeit zwischen zwei Aufrufen
        self.last_action_delay = 300                      # 300 s, bevor die Methode self.handle_action aufgerufen wird
        self._last_action_time_checker()

    def _last_action_time_checker(self):
        if self.last_action_time:
            if (time.time - self.last_action_time) > self.last_action_delay:
                self.last_action_time = 0                # Sicherstellen, dass die Aktion nur einmal pro Ablauf ausgeführt wird
                self.handle_action()
        self.after(self.last_action_time_poll_interval, self._last_action_time_checker)

    def handle_action(self):
        "Handle action after n seconds"

    def any_callback(self, event=None):
        self.last_action_time = time.time           # setzt den Counter auf die aktuelle Zeit hoch -> Differenz = 0
Wie gesagt, ist gerade ungetestet!
Ich habe gleich noch ein paar Steuervariablen eingebaut, so dass Du jederzeit die Abfragehäufigkeit und Dauer der Verzögerung anpassen kannst (Achtun, erstes in ms, zweites in s).

Siehe auch hier zur after-Methode: http://effbot.org/tkinterbook/widget.htm

Grüße,
Michael

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Montag 24. November 2014, 13:33
von schnibli
Vielen Dank für deine Antwort

Ich habe beim handel:
Print("ich bin fertig") hineingeschrieben(zum testen)

Wenn ich das Programm starte erscheint leider nie eine meldung

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Montag 24. November 2014, 13:41
von BlackJack
@schnibli: So auf den ersten Blick fehlt bei den `time.time()` jeweils die Klammern zum Aufrufen der Funktion.

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Montag 24. November 2014, 13:46
von schnibli
Dies scheint leider nicht das Problem zu sein:

Code: Alles auswählen

self.last_action_time = time.time()           # setzt den Counter auf die aktuelle Zeit hoch -> Differenz = 0

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Montag 24. November 2014, 19:16
von Michael Schneider
@schnibli,
bitte auch in Zeile 14 ändern. Ich kann den Post leider nicht bearbeiten.

BlackJack hat natürlich recht, ich habe nicht aufgepasst und das mit web2py verwechselt, wo man als Referenz für die aktuelle Zeit die Ankunftzeit im Requestobjekt verwenden kann.
time.time ist eine Funktion.

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Montag 24. November 2014, 19:28
von jens
Ich denke mal sollte besser per event handler schauen wann sich zuletzt die Maus bewegt und wann zulest eine taste gedrückt wurde...

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Montag 24. November 2014, 22:53
von Michael Schneider
Hi Jens,
jens hat geschrieben:Ich denke mal sollte besser per event handler schauen wann sich zuletzt die Maus bewegt und wann zulest eine taste gedrückt wurde...
welchen event Handler meinst Du? Wenn ich schnibli richtig verstanden habe, soll das Bild nach 5 Minuten angezeigt werden, wenn gerade nichts passiert ist (keine Bewegung und kein Tastendruck). Wie würdest Du das ohne Polling machen?
Man könnte auch einen after-Handler auf 5 Minuten stellen und dann prüfen, ob tatsächlich seit 5 Minuten keine Benutzerinteraktion stattfand. Dann würde sich aber eine Handler-Schlange aufbauen.

Grüße,
Michael

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Dienstag 25. November 2014, 10:08
von jens
Hab bei Test Skript gemacht: http://www.python-forum.de/viewtopic.php?f=11&t=35134

Demnach würde ich "Motion", "KeyPress" und "Configure" (Fenster verschieben) benutzten. Das sollte genug an Aktivität zeigen.
Ein event-Handler, der dann nur self.last_action_time = time.time() setzt.

Dann mit .after() regelmäßig prüfen, ob 5 Min schon vorbei sind.

Aber mal ehrlich, wozu das ganze? Dafür gibt es ja den "Bildschirmschoner" vom OS...

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Dienstag 25. November 2014, 10:27
von Michael Schneider
jens hat geschrieben:Demnach würde ich "Motion", "KeyPress" und "Configure" (Fenster verschieben) benutzten. Das sollte genug an Aktivität zeigen.
Ein event-Handler, der dann nur self.last_action_time = time.time() setzt.

Dann mit .after() regelmäßig prüfen, ob 5 Min schon vorbei sind.
Ok, und in wie weit unterscheidet sich das von meinem Vorschlag? :-)
In Deinem verlinkten Beitrag verknüpfst Du alle Events mit derselben Methode "_update_status". Aber ich denke, es geht nicht NUR um das Zurücksetzen des Counters, sondern es sollen je nach Event auch unterschiedliche Aktionen ausgeführt werden. In meinem Vorschlag wird für jede Aktion eine callback-Funktion erstellt, die zusätzlich zum Handler-Code die eine Zeile zum aktualisieren der Zeit enthalten soll.

VG,
Michael

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Dienstag 25. November 2014, 10:37
von BlackJack
@jens: In diesem Fall soll dem Benutzer vor dem Bildschirmschoner anscheinend was angezeigt werden. Manchmal hat man ja auch Software die wenn nichts passiert nach einer gewissen Zeit in einen Demomodus wechselt, der dem Benutzer verschiedene Möglichkeiten aufzeigt.

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Dienstag 25. November 2014, 11:21
von Michael Schneider
BlackJack hat geschrieben:Manchmal hat man ja auch Software die wenn nichts passiert nach einer gewissen Zeit in einen Demomodus wechselt, der dem Benutzer verschiedene Möglichkeiten aufzeigt.
... oder ein Bild seiner Freundin. :mrgreen:

Zu meinem Code: vielleicht liegt ein Missverständnis vor. Die Funktion "any_callback" soll so nicht wörtlich heißen und ein Callback für alle Userevents sein. Vielmehr sollte 'any' eine Art Platzhalter für alle möglichen Benutzerevents darstellen, also "buttonpress_callback", "keyup_callback", "motion_callback" usw., für die jeweils eine Methode geschrieben wird, welche die eine Zeitsetzzeile enthalten soll. Das hätte ich dazu schreiben sollen.

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Dienstag 25. November 2014, 11:30
von jens
Also ich glaube es sollte alle Informationen ausgetauscht worden sein, um das zu realisieren. Halt die Teile zusammen Puzzeln :D

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Dienstag 25. November 2014, 18:41
von schnibli
Vielen Dank, ich wollte mal zum Testen das erste Beispiel zum laufen bringen:

Code: Alles auswählen

import tkinter as tk
import time
 
class MainWindow(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.last_action_time = 0
        self.last_action_time_poll_interval = 1000  # 1000 ms min. Zeit zwischen zwei Aufrufen
        self.last_action_delay = 10                      # 300 s, bevor die Methode self.handle_action aufgerufen wird
        self._last_action_time_checker()
 
    def _last_action_time_checker(self):
        if self.last_action_time:
            if (time.time() - self.last_action_time) > self.last_action_delay:
                self.last_action_time = 0                # Sicherstellen, dass die Aktion nur einmal pro Ablauf ausgeführt wird
                self.handle_action()
        self.after(self.last_action_time_poll_interval, self._last_action_time_checker)
 
    def handle_action(self):
        print("hallo ich bin fertig")         
    def any_callback(self, event=None):
        self.last_action_time = time.time()           # setzt den Counter auf die aktuelle Zeit hoch -> Differenz = 0
Dies Teste ich auf einem Windows Rechner mit Python3.4.1 und es kommt nie die Meldung "ich bin fertig" :s

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Dienstag 25. November 2014, 19:35
von jens
Pack mehr print rein und schau dir so Werte an bzw. zeig dir an, welche Methoden aufgerufen bzw. nicht aufgerufen werden. :wink:

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Dienstag 25. November 2014, 19:59
von schnibli
Das Programm wird gleich geschlossen, es wird nicht offen gehalten :)....

Irgendwas fehlt aber steh gerade auf dem schlauch ^^

Code: Alles auswählen

try:
    import tkinter as tk
except:
    import Tkinter as tk
import time
        
class MainFrame():
    

    def __init__(self):
        tk.Tk.__init__(self)
        self.last_action_time = 0
        self.last_action_time_poll_interval = 1000  # 1000 ms min. Zeit zwischen zwei Aufrufen
        self.last_action_delay = 10                      # 300 s, bevor die Methode self.handle_action aufgerufen wird
        self._last_action_time_checker()
 
    def _last_action_time_checker(self):
        if self.last_action_time:
            if (time.time() - self.last_action_time) > self.last_action_delay:
                self.last_action_time = 0                # Sicherstellen, dass die Aktion nur einmal pro Ablauf ausgeführt wird
                self.handle_action()
        self.after(self.last_action_time_poll_interval, self._last_action_time_checker)
 
    def handle_action(self):
        print("hallo ich bin fertig")        
    def any_callback(self, event=None):
        self.last_action_time = time.time()           # setzt den Counter auf die aktuelle Zeit hoch -> Differenz = 0


print ("Programm beendet")

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Dienstag 25. November 2014, 21:00
von Michael Schneider
Hi Schnibli,

wie sieht denn dein ganzes Programm aus, d.h. wo wird das tk.Tk Hauptfenster instanziert und die Eventschleife initialisiert?
Und wo ist die tk.Tk Basisklasse aus den Klammern hinter "class MainFrame" geblieben?

Wenn man unter Windows ein python-Skript per Doppelklick startet, öffnet sich im Hintergrund ein Kommandofenster, das verschwindet, wenn der Programmablauf am Ende ankommt. Das kann passieren, wenn die Tkinter Eventschleife beendet wird, aber auch wenn ein Fehler auftritt. Du musst dafür sorgen, dass das Fenster erhalten bleibt, um die ausgegebene Fehlermeldung zu lesen. Dazu fängst Du entweder global eventuelle Fehler ab und verzögerst das Ende z.B. mit "raw_input()".
Oder einfacher, Du öffnest erst eine Windows Eingabeaufforderung (startmenü -> "cmd") und führst dort das Skript aus. Die schließt sich nicht, auch wenn das Skript mit einem Fehler abbricht.

Grüße,
Michael

Re: Nach 5min Inaktiv Bild anzeigen

Verfasst: Freitag 28. November 2014, 15:38
von schnibli
Hallo, ich kriege folgenden fehler bei:

Code: Alles auswählen

        self.after(self.last_action_time_poll_interval, self._last_action_time_checker)

Code: Alles auswählen

AttributeErrot: 'MainFrame' object has no attribute 'after'