4TV
Professeurs référents :
M FAURY (ISN)
Présentation de l’équipe projet
VASSEUR Quentin │ VERNAT Gatien │ FAYT Teddy
projetisn.4tv@gmail.com
Année scolaire 2016/2017 TS5
Objectif
Créer une application sur ordinateur permettant de trouver le programme de télévision qui correspond le mieux aux différents critères de recherche de l’utilisateur.
L’application permettra également une navigation facile des différentes chaînes de télévision, pourra permettre une mémoire des goûts de l’utilisateur et une modification de certains paramètres.
Elle ira trouver toutes les informations nécessaires directement sur le WEB ( fichier XML) et sera codée en python.
Possibilité d’intégrer une application sur smartphone/tablette qui communique avec l’ordinateur.
Présentation du projet
- Comment trouver le programme télé qui correspond parfaitement à notre envie du jour, en deux clics ?
- Pour construire cette application, certaines compétences devront être requises :
Critères |
Place dans le projet |
Création d’algorithme | Moteur du projet |
Éléments de programmation | Python ( et peut être Java) Développement en algorithmique simple et/ou POO |
Utilisation des réseaux | Enregistrement en ligne des données et communication avec appli android |
Droits et responsabilité | Protéger l’application et les données enregistrées |
- Contraintes pour la mise en place du projet : Maitrise de Python, Tkinter, peut-être Java et les sockets pour l’appli Smartphone et Tablette.
- Ressources : Pyzo, certaines librairies de python devront s’imposer (BS4, Tkinter) !
- Projet largement faisable dans la théorie, à suivre …
Tâches à réaliser :
(Cliquez ici pour dérouler)
[reveal heading= »%image% Tâches détaillées »]Mot-clés | Description | Détail des tâches |
|
Réaliser un algorithme qui permet la recherche du fichier XML du jour et procéder à sa lecture. |
|
|
Créer la fenêtre, les différents éléments de transmission ( boutons, choix-listes, …) et les boites de dialogues. |
|
|
Créer la fenêtre de chargement, celle de la sélection du mode et celle pour afficher les résultats |
|
|
Afficher l’application dans une fenêtre avec des graphismes simples qui rendront l’application intuitive. |
|
|
Réaliser un algorithme qui permet de prendre en compte les choix de l’utilisateur et les communiquer. |
|
|
Rechercher un système qui mémorise les goûts de l’utilisateur ( mémoire du PC ou en ligne ). |
|
|
Réaliser un algorithme qui permet à l’utilisateur de modifier certains paramètres. |
|
|
Réaliser un algorithme qui permet la navigation sur les différentes chaines pour voir les programmes TV. |
|
|
Si possible, application en Java qui communique avec l’ordinateur |
|
Répartition des tâches
Nom de l’élève | Vernat Gatien | Fayt Teddy | Vasseur Quentin |
Taches |
|
|
|
Suivi collectif du projet et co-évaluation :
(Cliquez ici pour dérouler)
[reveal heading= »%image% Déroulement des actions de groupes »]
Nom | Date | Étape/Tâche | État d’avancement | Remarques |
Quentin | 17/02 | FICHIER | Début | Recherche sur bs4, début programmation |
Gatien | 17/02 | INTERFACE | Formation de la fenêtre | |
Quentin | 3/03 | FICHIER | Fin | Fichier se télécharge, se dézippe et initialisation correcte |
Gatien | 03/03 | INTERFACE | Ajout des boutons et label au sein de la fenêtre | |
Quentin | 10/03 | CRITERES | Début | Reflexion sur la logique de l’algorithme |
Gatien | 10/03 | INTERFACE | Création des premiers menus déroulants et ligne de saisis | |
Quentin | 24/03 | CRITERES | En cours | Adaptation à l’initialisation |
Gatien | 24/03 | INTERFACE | Problème avec le menu déroulant | |
Quentin | 7/04 | CRITERES | Fin | Fonctionne |
Gatien | 07/04 | INTERFACE | Création des listes contenus dans les menus | |
Quentin | 14/04 | APPLICATION ANDROID | Début | Interface graphique réalisée |
Gatien | 14/04 | INTERFACE | Nouvelle forme de menu déroulant | |
Quentin | 21/04 | APPLICATION ANDROID | En cours | Connexion avec l’ordi et envoi des données |
Gatien | 21/04 | INTERFACE | Bouton de recherche lançant l’algorithme | |
Quentin | 28/04 | APPLICATION ANDROID | Fin provisoire | Problèmes communication des résultats |
Gatien | 28/04 | INTERFACE | Mise en commun avec la partie algorithmes | |
Quentin | 5/05 | INTERFACE 2 | Début | Renseignement sur affichage en liste |
Gatien | 05/05 | INTERFACE | Association de terme par champs lexical (algorithme) | |
Quentin | 12/05 | INTERFACE 2 | Fin | Fonctionne avec tout type de résultats |
Gatien | 12/05 | INTERFACE 2 | Aide au positionnement des données sur la fenêtre |
Au cours de notre projet, la démarche collaborative c’est effectuée de la manière suivante :
- Une séance hebdomadaire de 2h de ISN durant 10 semaines
- Des modules portable (clé usb) sur lesquels nous pouvions transporté notre travail
- L’ensemble de notre travail sur un espace de stockage en ligne (Drive), modifiable par tous à tous moment
- L’ensemble des outils de communication (téléphone, réseaux sociaux…)
Ressources documentaires et documentation du projet
Liste des références consultées pour le projet :
Besoins | URL |
Récupérer le fichier XMLTV | http://xmltv.dtdns.net/download/ |
Apprendre Tkinter | http://apprendre-python.com/page-tkinter-interface-graphique-python-tutoriel |
Modules à installer avec pip | http://www.lfd.uci.edu/~gohlke/pythonlibs/ |
Documentations officielles de modules Python | https://www.crummy.com/software/ |
Analyse de la dimension sociétale, juridique du projet
- Possibilité d’ouvrir un réseau et de commercialiser l’application android
- Protéger l’application, les données des utilisateurs, …
Code Complet
# -*- coding: utf-8 -*- #import from zipfile import ZipFile from urllib.request import urlretrieve, urlopen from bs4 import BeautifulSoup import os from datetime import date, timedelta import datetime import unicodedata import time import socket from tkinter import * import tkinter.messagebox from threading import Thread from PIL import ImageTk, Image import base64 import PIL.Image from io import BytesIO lstresults =[] threadstop = 0 soup = None dicochaine = None ooui= input('Port de la clé > ') namefile = ooui + ":/ISN/PROJET- 4TV/python/xmltv/tnt-" \ + str(date.today().day) \ +str(date.today().month)+str(date.today().year)+".xml" # try: # os.remove(namefile) # except: # pass # print("Ancien fichier supprimé") #Transformer un noeud xml en str def transformer(totrans, noeud,n1,n2): typefind = str(totrans) return typefind[len(noeud)+n1:len(typefind)-(len(noeud)+n2)].encode('utf-8').decode('UTF-8') #init chaque jour def dezipsave(): global threadstop t = time.time() global soup,dicochaine, dicologos, dicoinverse if os.path.isfile(namefile) == False: dossier = ooui+":/ISN/PROJET- 4TV/python/xmltv" for file in os.listdir(dossier): os.remove(dossier+"/"+file) file, header = urlretrieve("http://xmltv.dtdns.net/download/tnt.zip") print("fichier télechargé") # dézippage ZipFile(file).extractall(path=dossier, members=None, pwd=None) print("fichier dézippé") # renommer os.rename(ooui+":/ISN/PROJET- 4TV/python/xmltv/tnt.xml", namefile ) print("renommé") #soup print("chargement du soup...") soup = BeautifulSoup(open(namefile, encoding = "UTF-8",errors='ignore'), 'lxml-xml') #import des chaines et leur code dans un dico dicochaine = {} dicologos = {} dicoinverse = {} for chaine in soup.find_all('channel'): dicochaine[chaine.get('id')] = transformer(chaine.find_all('display-name'), 'display-name',3,4) dicologos[chaine.get('id')] = ooui+":/ISN/PROJET- 4TV/Drawables/logos/" + chaine.icon.get('src').split('/')[3] for cle,valeur in dicologos.items(): dicoinverse[valeur] = cle print("fin initialisation",time.time()-t) threadstop = 1 #tout en minuscule def allminuscule(str): lettres = [c for c in str] n = 0 for lettre in str: if 65 <= ord(lettre) <= 90: lettres[n] = chr(ord(lettre)+32) n += 1 return "".join(lettres) # enlever accent def decodage(str): return allminuscule(unicodedata.normalize('NFD', str).encode('ascii','ignore').decode('utf-8')) #Présence d'un mot def mottest(mot, texte): return decodage(mot) in decodage(texte).split() #Présence d'au moins un mot def phrasetest(phrase,texte): for mot in decodage(phrase).split(): if decodage(mot) in decodage(texte).split(): return True return False #renvoie une date à partir d'un str ( ex 20170320) def dater(date): return datetime.datetime(int(date[0:4]),int(date[4:6]),int(date[6:8]),int(date[8:10]),int(date[10:12])) #test d'un mot dans le nom du programme def nomtest(nom, title): for mot in nom.split(): if mottest(mot,title) and (not decodage(mot) in ["le","la","les","un","une","des", "ce","ces","de","!",":",",",".","?",";"]): return True return False #coeur def recherche(typechoisi,genrechoisi,nomrealisateur,nomchoisi): listeprogramme = [] dateaujn = datetime.datetime.fromordinal((date.today()+ timedelta(days=5)).toordinal()) for programmes in soup.find_all('programme'): if dater(programmes.get('start')) > dateaujn or datetime.datetime.now() > dater(programmes.get('stop')): pass else: catnum = 0 progtype = 0 for categories in programmes.find_all('category'): typegenre = transformer(categories,'category',12,3) if mottest(typechoisi,typegenre) and catnum == 0: progtype = 1 nom1fois = 0 duree = int((dater(programmes.get('stop'))-dater(programmes.get('start'))).total_seconds()) dureetot = str(duree//3600)+"h "+str((duree%3600)//60)+"m"#+str(duree%3600%60//60)+"s" chaine = dicologos[programmes.get('channel')]#dicochaine[programmes.get('channel')] start = dater(programmes.get('start')) titre = transformer(programmes.find_all('title'),'title',3,4) soustitre = transformer(programmes.find_all('sub-title'),'sub-title',3,4) imgprog = programmes.icon.get('src') realisateur = "" try: realisateur = transformer(programmes.credits.director,"director",2,3) except: pass donneesprogs = [chaine, titre, soustitre, realisateur, start, dureetot,imgprog] elif (phrasetest(genrechoisi, typegenre) or genrechoisi == "") and progtype == 1: if phrasetest(nomrealisateur,realisateur) or nomrealisateur == "": if nomtest(nomchoisi,titre) or nomchoisi == "": nom1fois = 1 listeprogramme.append(donneesprogs) if nomtest(nomchoisi,titre) and nom1fois == 0: nom1fois = 1 listeprogramme.append(donneesprogs) elif progtype == 1 and nom1fois == 0 and nomtest(nomchoisi,titre) : listeprogramme.append(donneesprogs) catnum =1 return sorted(listeprogramme, key = lambda x:x[4]) def critereandroid(): soc = socket.socket() host = socket.gethostbyname(socket.gethostname()) port = 11000 print(host) soc.bind((host, port)) soc.listen(5) result =[] for n in range(4): conn, adr = soc.accept() commande = str(conn.recv(1024).decode('UTF-8'))[2:] if phrasetest(commande, "Choisissez"): result.append("") else: result.append(commande) print("données reçues") return result def gererresultats(listedonnees): if listedonnees[1] == "Choisissez un genre": listedonnees[1] = "" #film if listedonnees[1] == "Action": listedonnees[1] = "d'action catastrophe d'aventures" if listedonnees[1] == "Animation": listedonnees[1] = "d'animation" if listedonnees[1] == "Horreur": listedonnees[1] = "d'horreur" if listedonnees[1] == "Film documentaire": listedonnees[1] = "documentaire biographie" #série if listedonnees[1] == "Humoristique": listedonnees[1] = "burlesque humoristique" if listedonnees[1] == "Judiciaire": listedonnees[1] = "judiciaire carcérale" #documentaire if listedonnees[1] == "Culture": listedonnees[1] = "beaux-arts culture lettres théâtre" if listedonnees[1] == "Découverte/Histoire": listedonnees[1] = "découvertes histoire civilisations" if listedonnees[1] == "Politique": listedonnees[1] = "géopolitique politique société" return listedonnees def updategenre(val): global lstgenre genrelist = OptionMenu(fenetre,choixgenre,"") genrelist['menu'].delete(0, 'end') if choixtype.get() == "Film": lstgenre = ["Action","Animation","Comédie","Comédie dramatique", "Comédie sentimentale","Court métrage","Drame","Horreur","Guerre", "Science-fiction","Suspense","Fantastique","Film documentaire", "Policier","Jeunesse","Thriller","Western"] elif choixtype.get() == "Série": lstgenre = ["Action","Animation","Guerre","Science-fiction","Suspense","Dramatique", "Fantastique","Historique","Hospitalière","Humoristique","Judiciaire", "Policière","Réaliste","Téléréalité","Erotique"] elif choixtype.get() == "Documentaire": lstgenre = ["Animalier","Autre","Aventures","Cinéma","Culture","Découverte/Histoire", "Economie","Education","Environnement","Erotique","Fiction","Gastronomie", "Politique","Musique","Pêche/Chasse","Santé","Sciences et Technique","Sport","Téléréalité"] elif choixtype.get() == "Magazine": lstgenre = ["Actualité","Animalier","Culinaire","Culturel","Actualité","Charme", "Découvertes","Politique","Art de Vivre","Automobile","Environnement", "Economie","Santé","Reportages","Services","Société","Télé-Achat","Loisirs", "Cinéma","Jeunesse","Judiciaire","Musique","Sport","Scientifique"] elif choixtype.get() == "Sport": lstgenre = ["Basket-ball","Biathlon","Combat","Journal Sport","Cyclisme","E-Sport", "Equitation","Football","Fitness","Sports Mécaniques","Golf","Sport de Glisse", " Multisports","Pétanque","Rugby","Snooker","Sports Nautiques","Volley-ball"] elif choixtype.get() == "Emission": lstgenre = ["Spéciale","Bien-être","Jeunesse","Talk-Show","Variétés","Voyance","Politique", "Musique","Interview","Téléréalité"] elif choixtype.get() == "Journal": lstgenre = ["Journal"] elif choixtype.get() == "Dessin animé": lstgenre = ["Dessin Animé","Jeunesse","Manga"] elif choixtype.get() == "Autre": lstgenre = ["Autre","Loterie"] elif choixtype.get() == "Divertissement": lstgenre = ["Divertissement","Humour","Voyance","Musique","Jeu"] elif choixtype.get() == "Météo": lstgenre = ["Météo"] else: lstgenre = ["Réaliste","Sentimentale"] genrelist = OptionMenu(fenetre,choixgenre,*lstgenre) genrelist.grid(column=1,columnspan=2,row=3,sticky = E) def rechercher(): if choixtype.get() != "Choisissez un type": global lstresults,threadstop, lsjours, dicoresults, uniquecesoir dicotrad = {0:'Lundi',1:'Mardi',2:'Mercredi',3:'Jeudi',4:'Vendredi',5:'Samedi',6:'Dimanche'} if time.localtime()[6]+2 < 7: jour3 = dicotrad[time.localtime()[6]+2] else: jour3 = dicotrad[(time.localtime()[6]+2)-7] if time.localtime()[6]+3 < 7: jour4 = dicotrad[time.localtime()[6]+3] else: jour4 = dicotrad[(time.localtime()[6]+3)-7] if time.localtime()[6]+4 < 7: jour5 = dicotrad[time.localtime()[6]+4] else: jour5 = dicotrad[(time.localtime()[6]+4)-7] lsjours =["Aujourd'hui","Demain",jour3,jour4,jour5] lstresults = recherche(*gererresultats([choixtype.get(), choixgenre.get(), prec.get(), nomprog.get() ])) Label(fenetre, text="").grid(column=0,row=6) chargementbut = Label(fenetre, text="Chargement ...") chargementbut.grid(column=2,row=8) fenetre.update() threadstop = 1 dicoresults = {} n = 0 for jours in lsjours: lstdatejour =[] for progs in lstresults: if (progs[4]<datetime.datetime.fromordinal((date.today()+ timedelta(days=n+1)).toordinal())) \ and (progs[4]>datetime.datetime.fromordinal((date.today()+ timedelta(days=n)).toordinal())): lstdatejour.append(progs) dicoresults[jours] = lstdatejour n+=1 uniquecesoir = checkvalue.get() else: tkinter.messagebox.showinfo("Attention", "Vous devez d'abord choisir un type") class VerticalScrolledFrame(Frame): def __init__(self, parent, *args, **kw): Frame.__init__(self, parent, *args, **kw) vscrollbar = Scrollbar(self, orient=VERTICAL) vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE) canvas = Canvas(self, bd=0, highlightthickness=0, yscrollcommand=vscrollbar.set) canvas.pack(side=LEFT, fill=BOTH, expand=TRUE) vscrollbar.config(command=canvas.yview) canvas.xview_moveto(0) canvas.yview_moveto(0) self.interior = interior = Frame(canvas) interior_id = canvas.create_window(0, 0, window=interior, anchor=NW) def _configure_interior(event): size = (interior.winfo_reqwidth(), interior.winfo_reqheight()) canvas.config(scrollregion="0 0 %s %s" % size) if interior.winfo_reqwidth() != canvas.winfo_width(): canvas.config(width=interior.winfo_reqwidth()) interior.bind('<Configure>', _configure_interior) ##♣Lancement def androidbut(): fenmode.destroy() lstrech = [] for rech in gererresultats(critereandroid()): lstrech.append(rech) print(lstrech) for progs in recherche(*lstrech): print(progs) def ordibut(): global threadstop threadstop = 1 threadinit= Thread(None, dezipsave) threadinit.start() feninit = Tk() feninit.geometry('%dx%d+%d+%d' % (300, 200, (feninit.winfo_screenwidth()/2)-150, (feninit.winfo_screenheight()/2)-100)) feninit.resizable(0,0) titre = Label(feninit, text="Lancement de 4TV") titre.grid(column=1,row=0) Frame(feninit,height=1,width = 300,bg="black").grid(column=0,row=1,columnspan = 3) strcharge = " " titre = Label(feninit, text="Chargement "+strcharge) titre.grid(column=1,row=2) feninit.iconbitmap(ooui+':/ISN/PROJET- 4TV/Drawables/logofin.ico') while threadstop != 1 : strcharge =" " titre.config(text = "Chargement "+strcharge) feninit.update() time.sleep(1) strcharge =". " titre.config(text = "Chargement "+strcharge) feninit.update() time.sleep(1) strcharge =". . " titre.config(text = "Chargement "+strcharge) feninit.update() time.sleep(1) strcharge =". . ." titre.config(text = "Chargement "+strcharge) feninit.update() time.sleep(1) titre.config(text = "Chargement terminé") feninit.update() time.sleep(1) threadstop = 0 feninit.destroy() fenmode = Tk() fenmode.geometry('%dx%d+%d+%d' % (300, 200, (fenmode.winfo_screenwidth()/2)-150, (fenmode.winfo_screenheight()/2)-100)) fenmode.resizable(0,0) mode = Label(fenmode, text="Choisissez un mode") mode.grid(column=1,row=0) Frame(fenmode,height=1,width = 300,bg="black").grid(column=0,row=1,columnspan = 3) androidbutton = Button(fenmode, text="Android", command=androidbut) androidbutton.grid(column=0,row=2) ordibutton = Button(fenmode, text="Ordinateur", command=ordibut) ordibutton.grid(column=2,row=2) fenmode.iconbitmap(ooui+':/ISN/PROJET- 4TV/Drawables/logofin.ico') while threadstop != 1 : try: fenmode.update() except: pass fenmode.destroy() threadstop = 0 def retourfunc(): fenetreresultats.destroy() global threadstop threadstop = 0 while True: if threadstop != 1: lstgenre = [""] fenetre = Toplevel() fenetre.geometry('%dx%d+%d+%d' % (350, 230, (fenetre.winfo_screenwidth()/2)-175, (fenetre.winfo_screenheight()/2)-115)) fenetre.resizable(0,0) #BarreMenu recherchebut = Button(fenetre, text="Recherche") recherchebut.grid(column=0,row=0) navig = Button(fenetre, text="Navigation") navig.grid(column=1,row=0) param = Button(fenetre, text="Paramètres") param.grid(column=2,row=0) #Titre titre = Label(fenetre, text="Rechercher un programme") titre.grid(column=1,row=1) #LabelType type = Label(fenetre, text="Type :") type.grid(column=0,row=2,sticky = E) #OptionType choixtype = StringVar(fenetre) choixtype.set("Choisissez un type") lsttype = ["Film","Série","Documentaire","Magazine","Sport","Téléfilm","Emission","Divertissement","Journal","Météo","Dessin animé","Feuilleton","Autre"] typeoptions = OptionMenu(fenetre,choixtype,*lsttype, command=updategenre) typeoptions.grid(column=1,columnspan=2,row=2,sticky = E) #LabelGenre genre = Label(fenetre, text="Genre :") genre.grid(column=0,row=3,sticky = E) #OptionGenre choixgenre = StringVar(fenetre) choixgenre.set("Choisissez un genre") genrelist = OptionMenu(fenetre,choixgenre,"") genrelist.grid(column=1,columnspan=2,row=3,sticky = E) #LabelPrécision precision = Label(fenetre, text="Réalisateur :") precision.grid(column=0,row=4,sticky = E) #EntréePrécision prec = StringVar() precview = Entry(fenetre, textvariable=prec) precview.grid(column=1,columnspan=2,row=4,sticky = E,padx=10) #LabelNom nom = Label(fenetre, text="Nom :") nom.grid(column=0,row=5,sticky = E) #EntréeNom nomprog = StringVar() nomview = Entry(fenetre, textvariable=nomprog) nomview.grid(column=1,columnspan=2,row=5,sticky = E,padx=10) #Mode uniquement ce soir uniquelabel = Label(fenetre, text="Uniquement aujourd'hui") uniquelabel.grid(column=0,row=6,sticky = E) checkvalue = BooleanVar() checksoir = Checkbutton(fenetre, text="", variable=checkvalue) checksoir.grid(column=2,row=6,sticky = E) #Ligne vide Label(fenetre, text="").grid(column=0,row=7) #SearchButton searchbutton = Button(fenetre, text="Rechercher", command=rechercher) searchbutton.grid(column=1,row=8) fenetre.iconbitmap(ooui+':/ISN/PROJET- 4TV/Drawables/logofin.ico') while threadstop != 1 : try: fenetre.update() except: pass fenetreresultats = Toplevel() fenetreresultats.resizable(0,0) retourbut = Button(fenetreresultats, text="Retour", command=retourfunc) retourbut.pack() if lstresults != []: frame1 = VerticalScrolledFrame(fenetreresultats) frame1.pack() list1 = Listbox(frame1.interior) i = 0 ii = 0 lstImage = [] lstlogos =[] if uniquecesoir == True: for element in dicoresults["Aujourd'hui"]: p = Frame(list1) for el in element: if (str(el)[-3:] == 'jpg'): try: lstImage.append(ImageTk.PhotoImage(PIL.Image.open(BytesIO(urlopen(str(el)).read())).resize((50, 50), PIL.Image.ANTIALIAS))) Label(p, image = lstImage[i]).pack(side=LEFT) i+=1 except: pass elif (str(el)[-3:] == 'gif'): try: lstlogos.append(ImageTk.PhotoImage(PIL.Image.open(str(el)))) Label(p, image = lstlogos[ii]).pack(side=LEFT) ii+=1 except: Label(p, text=dicochaine[dicoinverse[el]]).pack(side=LEFT, expand=100) else: Label(p, text=str(el)).pack(side=LEFT, expand=100) p.pack(fill=BOTH) list1.insert(END, p) else: for jours in lsjours: p1 = Frame(list1) jourlist = Label(p1, text=jours).pack() p1.pack(fill=X) list1.insert(END, p1) for element in dicoresults[jours]: p = Frame(list1) for el in element: if str(el)[-3:] == 'jpg': try: lstImage.append(ImageTk.PhotoImage(PIL.Image.open(BytesIO(urlopen(str(el)).read())).resize((50, 50), PIL.Image.ANTIALIAS))) Label(p, image = lstImage[i]).pack(side=LEFT) i+=1 except: pass elif (str(el)[-3:] == 'gif'): try: lstlogos.append(ImageTk.PhotoImage(PIL.Image.open(str(el)))) Label(p, image = lstlogos[ii]).pack(side=LEFT) ii+=1 except: Label(p, text=dicochaine[dicoinverse[el]]).pack(side=LEFT, expand=100) else: Label(p, text=str(el)).pack(side=LEFT, expand=100) p.pack(fill=BOTH) list1.insert(END, p) list1.pack(side=LEFT, fill= BOTH, expand= 1) frame1.update() fenetreresultats.geometry('%dx%d+%d+%d' % (frame1.winfo_width(),300, (fenetreresultats.winfo_screenwidth()/2)-(frame1.winfo_width())/2, (fenetreresultats.winfo_screenheight()/2)-150)) else: Label(fenetreresultats, text= "Aucun resultat").pack() fenetreresultats.geometry('%dx%d+%d+%d' % (300,300, (fenetreresultats.winfo_screenwidth()/2)-150, (fenetreresultats.winfo_screenheight()/2)-150)) fenetre.destroy() fenetreresultats.iconbitmap(ooui+':/ISN/PROJET- 4TV/Drawables/logofin.ico') else: try: fenetreresultats.update() except: pass
Aperçu du rendu final
« Fenêtre de recherche »
« Fenêtre de resultats »
« Application Android »
Fichiers du projet
- Ajouter un(des) fichier(s) puis cliquer sur Téléverser.
- Rafraichir la page pour vérifier que le dépôt a bien eu lieu.