[tkinter] Déclencher une tâche toutes les 5 minutes

Fermé
tatal21820 Messages postés 35 Date d'inscription vendredi 6 mai 2022 Statut Membre Dernière intervention 2 septembre 2023 - Modifié le 2 sept. 2022 à 12:07
mamiemando Messages postés 33081 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 avril 2024 - 5 sept. 2022 à 09:42

Bonjour à tous,

je voudrais savoir comment faire pour interroger mon agenda toutes les 5 min.

d'avance merci.

import io
import locale
import urllib.request
from datetime import timedelta, datetime
from tkinter import *
from tkinter import Tk
import icalendar
import pytz
import recurring_ical_events


locale.setlocale(locale.LC_ALL, 'fr_FR')

dat2 = datetime.now(pytz.timezone('Europe/Paris'))

master = Tk()
master.attributes('-fullscreen', True)
master.bind('<Escape>', lambda e: master.destroy())
master.config(background='black')

frm5 = LabelFrame(master, text='Tatal', font='helvetica 15', fg='WHITE', bg='black', height=800, relief=GROOVE)
frm5.place(x=20, y=250, width=500)


# Agenda Tatal
start_date = dat2.date()
end_date = start_date + timedelta(days=30)
url = "https://calendar.google.com/calendar/ical/xxxx@gmail.com/private-6490b3915a6375657d88645094940586" \
      "/basic.ics "

ical_string = urllib.request.urlopen(url).read()
calendar = icalendar.Calendar.from_ical(ical_string)
events = recurring_ical_events.of(calendar).between(start_date, end_date)

pdr = True
for event in events:
    pdr = False
    start = event["DTSTART"].dt
    duration = event["DTEND"].dt - event["DTSTART"].dt
    non = event["SUMMARY"]
    agd_tatal = Label(frm5, text=non + "  " + start.strftime("%A %d %B %H %M"), font='Arial 16', fg='WHITE', bg='black')
    agd_tatal.pack(padx=10, pady=10)
if pdr:
    agd_tatal = Label(frm5, text="Aucun rendez-vous aujourdhui", font='Arial 12', fg='WHITE', bg='black')
    agd_tatal.pack(padx=10, pady=10)


master.mainloop()


Windows / Chrome 104.0.0.0

5 réponses

mamiemando Messages postés 33081 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 avril 2024 7 749
Modifié le 2 sept. 2022 à 12:05

Bonjour,

Voici un exemple minimal montrant comment tu peux planifier l'exécution d'une tâche toutes les 2 secondes à l'aide de la méthode after.

from tkinter import *

root = Tk()

def task():
    print("hello")
    root.after(2000, task)  # reschedule event in 2 seconds

root.after(2000, task)
root.mainloop()

Dans ton cas il faut simplement remplacer 2000 par 5 * 60 * 1000 = 300000 et ta boucle d'événement s'appelle master au lieu de root.

Note que si tu veux que ta fonction task soit paramétrée, le plus élégant est d'écrire un foncteur, c'est à dire un objet qui implémente la méthode __call__ (sans paramètre autre que self) et dont le constructeur reçoit les paramètres en question.

Voici un exemple de foncteur (instancié, puis appelé 3 fois). Comme tu peux le voir, une fois le foncteur instancié, il se comporte comme une fonction qui, conformément à la signature de __call__, ne prend pas de paramètre.

class Task():
    def __init__(self, message):
        self.message = message
        self.interval = interval
    def __call__(self):
        print(self.message)

task = Task("hello")
task() # 1er appel
task() # 2e appel
task() # 3e appel

Maintenant, modifions un peu ce foncteur pour qu'il reçoive en paramètre l'intervalle de temps et qu'il se réenregistre dans la boucle d'événement à chaque fois qu'il est appelé. Le deux extraits de code précédents ainsi combinés permettent d'arriver à ceci :

from tkinter import *

root = Tk()

class Task():
    def __init__(self, message, interval = 1000):
        self.message = message
        self.interval = interval
    def __call__(self):
        print(self.message)
        root.after(self.interval, self)

interval = 2000
task = Task("hello", interval)
root.after(interval, task)
root.mainloop()

Tu notereras le second paramètre d'after devient self. En effet :

  • self correspond à notre foncteur (qu'on a appelé task au niveau du programme principal) et qu'on peut appeler comme une callback sans paramètre.
  • On ne doit/peut pas utiliser task dans __call__ car :
    • task n'est pas encore déclaré
    • même si elle était (genre en début de programme), il faut quand même utiliser self car dans le cas général, l'instance courante de Task n'est pas forcément nommée task.

Bonne chance

1
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 331
31 août 2022 à 23:15

Une boucle et l'utilisation de time.sleep ?


0
mamiemando Messages postés 33081 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 avril 2024 7 749
Modifié le 2 sept. 2022 à 12:51

Bonjour NHenry,

Une boucle et l'utilisation de time.sleep ?

  • Non, il ne faut pas faire utiliser sleep dans une boucle d'événements (cf master.mainloop()), car sinon, tu gèles l'interface pendant toute la durée du sleep.
  • Pour éviter ce problème, il faut enregistrer un événement que tu déclenches toutes les 5 minutes et que tu rattrapes dans une callback (voir message #3).
0
tatal21820 Messages postés 35 Date d'inscription vendredi 6 mai 2022 Statut Membre Dernière intervention 2 septembre 2023
2 sept. 2022 à 13:39

Merci beaucoup, mais je suis débutant et je vois pas comment l'intégrer dans mon interface.,

je rame.

UN grand merci quand même, je vais faire des essais.

0
mamiemando Messages postés 33081 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 avril 2024 7 749
Modifié le 5 sept. 2022 à 09:42

Dans ton cas la tâche à répéter toutes les 5 minutes est la récupération du calendrier ce qui correspond à la ligne 14 et aux lignes 31 à 45 de ton programme initial. Comme le traitement est paramétré par l'url et frm5, on peut soit déclarer une fonction task après avoir déclaré url et frm5, soit utiliser un foncteur.

Je n'ai pas testé car je n'ai pas installé icalendar, mais dans l'idée ça ressemblerait à ça :

import io
import locale
import urllib.request
from datetime import timedelta, datetime
from tkinter import *
import icalendar
import pytz
import recurring_ical_events

URL = "https://calendar.google.com/calendar/ical/xxxx@gmail.com/private-6490b3915a6375657d88645094940586" \
INTERVAL = 300000

master = Tk()
locale.setlocale(locale.LC_ALL, "fr_FR")
master.attributes("-fullscreen", True)
master.bind("<Escape>", lambda e: master.destroy())
master.config(background="black")
frm5 = LabelFrame(master, text="Tatal", font="helvetica 15", fg="WHITE", bg="black", height=800, relief=GROOVE)
frm5.place(x=20, y=250, width=500)

def task():
    # Agenda Tatal
    dat2 = datetime.now(pytz.timezone("Europe/Paris"))
    start_date = dat2.date()
    end_date = start_date + timedelta(days=30)
          "/basic.ics "

    ical_string = urllib.request.urlopen(URL).read()
    calendar = icalendar.Calendar.from_ical(ical_string)
    events = recurring_ical_events.of(calendar).between(start_date, end_date)

    pdr = True
    for event in events:
        pdr = False
        start = event["DTSTART"].dt
        duration = event["DTEND"].dt - event["DTSTART"].dt
        non = event["SUMMARY"]
        agd_tatal = Label(frm5, text=non + "  " + start.strftime("%A %d %B %H %M"), font="Arial 16", fg="WHITE", bg="black")
        agd_tatal.pack(padx=10, pady=10)
    if pdr:
        agd_tatal = Label(frm5, text="Aucun rendez-vous aujourdhui", font="Arial 12", fg="WHITE", bg="black")
        agd_tatal.pack(padx=10, pady=10)

    # Re-run this task in INTERVAL milliseconds
    master.after(INTERVAL, task)

master.after(INTERVAL, task)
master.mainloop()

Bonne chance

0
tatal21820 Messages postés 35 Date d'inscription vendredi 6 mai 2022 Statut Membre Dernière intervention 2 septembre 2023
2 sept. 2022 à 16:08

Merci,

ne marche pas, python me dit tasck "rename the element, Task " import this name"

0
mamiemando Messages postés 33081 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 avril 2024 7 749
3 sept. 2022 à 19:11

Peux-tu copier coller le message d'erreur exact ?

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
tatal21820 Messages postés 35 Date d'inscription vendredi 6 mai 2022 Statut Membre Dernière intervention 2 septembre 2023
4 sept. 2022 à 08:57

Bonjour, et merci pour ton dévouement, voici l'erreur.

Traceback (most recent call last):
  File "C:\Users\tatal\PycharmProjects\essais\essais.py", line 52, in <module>
    task = Task(URL, frm5, INTERVAL)
NameError: name 'Task' is not defined. Did you mean: 'task'?

0
mamiemando Messages postés 33081 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 avril 2024 7 749
5 sept. 2022 à 09:42

Ah c'est ma faute : il y avait une ligne incorrecte qui traînait dans le message #5, je l'ai corrigé. Peux-tu réessayer ?

0