Aller au contenu

[Resolu] [Python] créer un compteur graphique ?


Messages recommandés

DEBUT DU CODE (jutilise pas les balises code pour garder les commentaires verts)

from Tkinter import * #Importe le module graphique Tkinter

b=1 #variable de la boucle while

fenetre=Tk() #dessine la fenetre principale

texte=Label(fenetre,text="Compteur :") #cree le texte initial dans la fenetre principale

texte.grid(row=1,column=1) #alignement du texte a la ligne 1 et a la colonne 1

while b<5000: #boucle conditionelle qui s'arrete quand b arrive a 5000

_____print b #affiche la valeur actuelle de b dans le shell (fenetre DOS)

_____texte.configure(text="Compteur :" + str(b)) #edition du texte pour afficher la valeur actuelle de b

_____b=b+1 #incremente la boucle

fenetre.mainloop() #gestionnaire d'evenement qui rafraichit l'affichage de la fenetre

FIN DU CODE

;) salut ,amis programmeurs

je suis debutant sous python et je suis confronté a un casse tete dont je ne trouve pas la solution meme apres avoir consulté un max de docs

Voila mon probleme :

J'ai crée un logiciel capable de generer des grilles de loto a 6 numeros et cela grace a des boucles "While"

Ce logiciel calcule les occurences de chaque grille parmi un nombre de grilles rentrés (plusieurs centaines de milliers)

Je veux savoir en utilisant un compteur ou il en est dans la creation des grilles et dans la recherche des occurences afin de determiner le temps que lui prendra le calcul (par exemple une recherche d'occurences sur 50000 grilles lui prend 6minutes avant d'afficher le resultat)>>je veux un compteur en Temps reel

Vu que je n'arrive pas a faire marcher la fonction de comptage , je l'ai mise a part pour la tester elle seule ,

J'ai crée une interface graphique avec le module original de Python Tkinter (voir le script ci-dessus) pour percer le mystere et trouver la solution

J'ai constaté :

-la commande "print" affiche en temps reel la valeur de la variable "b" et cela dans la fenetre dos

-la methode "configure" de la classe "Label" est censée modifier le texte quand on l'appelle OR ce n'est que a la fin de la boucle (quand b atteint 5000) que cette foutue methode fait son boulot...grrrr :p

J'ai testé :

j'ai tenté d'utiliser des objets variables de type StrindVar() , IntVar() pour afficher en temps reel la valeur de b .....j'arrive a rien par manque de connaissance et d'exemples sur cette fonction

j'ai tenté la fonction event_generate qui genere des evenements de type "appui sur la touche A detecté" pour appeler la fonction de comptage ....pareil j'arrive a rien par manque de connaissance et d'exemples sur cette fonction

Votre aide :

J'aimerais connaitre vos avis sur la question et savoir quelle fonction fait pareil que la fonction "print" mais appliquée a un objet Label

:help: :dd:

Lien vers le commentaire
Partager sur d’autres sites

A ma connaissance si tu veux que ta fenetre graphique affiche en temps réel l'etat de ton opération et non qu'il bloque jusqu'au resultat, tu dois separer l'algorithme du calcul dans un processus a part, ensuite ce processus "met a jour" le contenu de ta fenetre avec une valeur.

oui j'ai testé ce que tu dis en utilisant un appel de fonction mais le probleme reste le meme

voici le code qui correspond a la separation des 2 algorithmes avec en rouge ce que j'ai ajouté:

from Tkinter import * #Importe le module graphique Tkinter

def comptage(b): # fonction appelée dans al boucle while avec l'argument "b"

_____texte.configure(text="Compteur :" + str(b)) #edition du texte pour afficher la valeur actuelle de b

b=1 #variable de la boucle while

fenetre=Tk() #dessine la fenetre principale

texte=Label(fenetre,text="Compteur :") #cree le texte initial dans la fenetre principale

texte.grid(row=1,column=1) #alignement du texte a la ligne 1 et a la colonne 1

while b<5000: #boucle conditionelle qui s'arrete quand b arrive a 5000

_____comptage(b)

_____b=b+1 #incremente la boucle

fenetre.mainloop() #gestionnaire d'evenement qui rafraichit l'affichage de la fenetre

FIN DU CODE

si tu peux exprimer ce que tu veux dire par un exemple de code ça pourrait m'aider :)

Lien vers le commentaire
Partager sur d’autres sites

mouhahahahhahaahh :francais:

j'ai trouvé une solution qui marche ==> la methode after() ...mais qui prend 1000 fois plus de temps de calcul :francais:

en gros je definis une fonction "A" qui genere UNE grille a 6 numeros....puis une deuxieme "B" qui regroupe toutes les grilles "A" et une 3eme "Compteur" qui apelle autant de fois que voulu "B" qui lui meme appelle "Compteur"

en gros "B" gagne une grille (en appellant "A") puis appelle "Compteur"... "Compteur" appelle "B" qui gagne une nouvelle grille en appellant "A" et ainsi de suite jusqua un certain nombre de grilles voulu...

l'affichage du compteur augmente de 1 et apres une milli seconde grace a la methode "after" """fenetre.after(1,tirageToutesLesGrilles)""" si je met la valeur a 0 le probleme revient, le calcul est trop rapide pour l'affichage graphique

jai compris le principe ...maitenant je dois l'appliquer a TOUT le programme...aaargghhhh une refonte complete est necessaire...

j'aurais donc 2 versions du programme...une ultra rapide sans indicateur d'etat et une autre super lente mais qui me dit ou il en est...

Lien vers le commentaire
Partager sur d’autres sites

rhaaaaa :transpi:

ça maaaaarche :francais:

ce code cree un compteur halucinament rapide....c un truc de psycopathe...

from Tkinter import * 
import threading


def comptage():
global b
while 1:
	b=b+1
	texte.configure(text="Compteur :"+ str(b))
	if b>500000:
		break

b=1  
t = threading.Thread(target=comptage)
fenetre=Tk()							
texte=Label(fenetre,text="Compteur :") 
texte.grid(row=1,column=1)			 
t.start()

fenetre.mainloop() 

merci oh venerable exelentissime tsubasaleguedin :craint:

maitenant je vais l'integrer dans le prog et je reposte pour la conclusion

au fait la page ou on trouve l'explication sur les threads THREAD

Lien vers le commentaire
Partager sur d’autres sites

bon le programme originel fonctionne bien , il est tres rapide grace au thread :fumer:

euh par contre le thread me cree un autre probleme...

impossible de l'arreter cet enfoiré....

je tente d'utiliser les methodes d'arret du methode Thread de threading....euhh je comprend pas coment ça marche...


def threadDeOuf():	 ##La fonction est demarée par le Bouton de lancement du programme
processus.start()


processus=threading.Thread(target=RunAll)  ##RunAll est la fonction qui lance le programme

a partir de la le code s'execute jusque a ce quil affiche les resultats....

mais pour l'arreter la commande serait

threading.Thread._Thread__stop

threading.Thread._Thread__stop(processus)
threading.Thread._Thread__delete(processus)

ça marhce pas...

Lien vers le commentaire
Partager sur d’autres sites

En faite c'est simple regarde mon exemple:

---------------------------------------------------------------------------------------------------------

----------Classe qui separe le processus--------------------------------------------------------

--------------------------------------------------------------------------------------------------------

import threading

class Thread(threading.Thread):

def __init__(self):

threading.Thread.__init__(self)

self.stop=False

def setStop(self):

"""Trip the stop flag."""

self.stop = True

def run(self):

while not self.stop and mon_autre_condition:

##Code ici de la thread

#print "Sorti de thread normal en fin de code"

return()

-----------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------

Dans ton programme pour demarrer le processus:

self.processus1= Thread(self)

self.processus1.start() ## Ce qui aura pour effet de demarrer la fonction run du processus

Apres pour arreter la thread un petit quand tu a envie de l'arreter:

self.processus1.setStop() ## Ce qui aura pour effet de mettre la variable "flag" à True et donc de le sortir de la boucle

Enfin il faut comprendre que des que le code d'execution de la methode run de ta class Thread est fini, le sous processus meurt..

Le but est d'avoir un control lors de sous processus long, donc de pouvoir l'arreter quand on veut, donc dans sa boucle du sous processus on prevoit la condition "Tant que la variable self.stop est pas vrai" en plus de ta condition a toi alors la boucle continue.

Donc la finalité de la chose est de creer une methode de la classe Thread (setStop) qui sert a mettre la variable à Vrai quand on l'appelle dans notre programme. Ce qui aura pour effet de faire sortir le processus de sa boucle meme si la condition originel est pas fini car on lui a dit de s'arreter aussi quand self.stop est vrai. Et a partir de la le sous processus s'arrete.

Tu peux creer autant de sous processus avec cette methode que tu veux, et les arreter un par un si tu le souhaite.

Lien vers le commentaire
Partager sur d’autres sites

Et bien essaye avec les def.

Tu modifie la condition dans la thread pour s'arreter quand self.stop est à True.

tu rajoute la fonction def setStop a ton programme et tu voie =) Mais je garantie pas le bon fonctionnement de la chose.

Quand j'utilise un processus separé j'aime bien que ce soit propre et je separe le processus dans une "class".

Par contre tu a besoin de passer a cette classe le "self" de ton programme principal si tu veux modifier des elements comme le compteur graphique et mettre le self recue dans une variable enfin c'est pas evident à expliquer imagine le programme suivant :

 
import threading

class Thread(threading.Thread):
def __init__(self,root): 
##Une fonction init créer ca propre racine aussi d'ou le self, 
##et on recoit notre parametre self.processus1= Thread(self) dans root
	threading.Thread.__init__(self) 
	self.root=root 
	##Je redefinie l'arbre des element de mon programme principal dans l'arbre de la classe donc 
	## dans self.root j'accede a tous les elements de mon programme self.root.mavariable 
	self.stop=False

def setStop(self):
	"""Trip the stop flag."""
	self.stop = True

def run(self):
	while not self.stop and mon_autre_condition:
		self.root.updatetext("montexte")
					## Au hasard c'est un exemple pour acceder a un element de ton 'self' original 
					##et non celui du thread car il connaitra pas l'element graphique
		##Code ici de la thread
	#print "Sorti de thread normal en fin de code"
	return()

self.processus1= Thread(self)
self.processus1.start() ## Ce qui aura pour effet de demarrer la fonction run du processus
time.sleep(500)
self.processus1.setStop()

Ensuite en WXwindows par exemple tu n'a pas le droit de modifier un element graphique dans un sous processus (meme si tu a accés a l'arbre d'objet en passant celui ci au processus) si celui ci ne lui appartient pas et tu dois creer on evenment qui demande a une fonction de ton programme de mettre a jour l'element en lui passant la valeur. Mais je veux pas te faire peur ca se trouve en TK tu n'est pas obliger de faire ca.

Lien vers le commentaire
Partager sur d’autres sites

chui completement depassé la...

mon prog marche comme ça dans les grandes lignes :

import threading
from random import randrange
from Tkinter import *


def RunAll():
v,valeur,err=0,0,0

valeur=entree.get() #get() renvoie une chaine
try :
	v=int(valeur) #conversion en valeur numerique
except:
	err=1  #entrée non numerique
else:
	err=0
if err==1 or v < 10 or v > 1e8:
	signaleErreur() #entree incorrecte ou hors limites
else:
	afficheresultats(occurences(tirage(v)))


def tirage(v): #tirage de grilles de 6 chiffres
def occurences(liste):
def afficheresultats(occurences):
def signaleErreur():
def videEntree():
def run():
	processus.start()



processus=threading.Thread(target=RunAll)

fenetre=Tk()
fenetre.title("LoTo SaKieBon : loto simple à 6 numéros")

#Creation du champ d'entree et de son texte
texte=Label(fenetre,text="Nombre de grilles à générer :",font="Arial 10 bold" )
texte.grid(row=1,padx=10,pady=5)
entree=Entry(fenetre,bg="grey")
entree.insert(0,"3000")
entree.grid(row=2,padx=10)

#Ce texte sera modifié par la suite pour afficher l'etat du tirage
texte2=Label(fenetre,text= "Grilles generées :",font="Arial 10 bold")
texte2.grid(row=4,padx=5,pady=5)

#Ce texte sera modifié par la suite pour afficher l'etat de la recherche d'occurence
texte3=Label(fenetre,text= "Recherche d'occurence :",font="Arial 10 bold")
texte3.grid(row=5,padx=5,pady=5)

#Ce texte sera modifié par la suite pour afficher les resultats
texte4=Label(fenetre,text= "Resultats :",font="Arial 10 bold")
texte4.grid(row=6,padx=5,pady=5)

#le Bouton unique qui declenche tout
Button(fenetre,text="Lancer la recherche d'occurences",font="Arial 10 bold",fg="black",bg="yellow",command=run).grid(row=3,padx=5,pady=10)

#creation d'un canevas pour y mettre deux images
can=Canvas(fenetre,width=120,height=150,bg="black")
photo=PhotoImage(file="panther.GIF")
photo2=PhotoImage(file="foraef.GIF")
item=can.create_image(60,60,image=photo)
item2=can.create_image(60,135,image=photo2)
can.grid(row=1,column=1,rowspan=6,padx=5,pady=15)

#demmarage de la boucle d'evenements
fenetre.mainloop()

tu peux me dire comment tu pourrais inclure l'arret de la thread ?

ps: la modif du texte se fait dans la def tirage(v) et def occurences(liste):

Lien vers le commentaire
Partager sur d’autres sites

En voyant ton code je vois que tu connais pas l'utilisation des arbres d'objets de python qui est fort pratique...

Je te conseil de lire ce livre en PDF qui est tres bon: http://www.ulg.ac.be/cifen/inforef/swi/dow...ython_notes.pdf

Qui saura en plus t'expliquer avec une pédagogie interressante toute les bases de la programmation objet qui rend python aussi interressant.

Sinon pour revenir a ton prog j'essayerai un truc du genre:

import threading
from random import randrange
from Tkinter import *


def RunAll():
while not stop
	v,valeur,err=0,0,0

	valeur=entree.get() #get() renvoie une chaine
	try :
		v=int(valeur) #conversion en valeur numerique
	except:
		err=1  #entrée non numerique
	else:
		err=0
	if err==1 or v < 10 or v > 1e8:
		signaleErreur() #entree incorrecte ou hors limites
	else:
		afficheresultats(occurences(tirage(v)))
return()

def tirage(v): #tirage de grilles de 6 chiffres
def occurences(liste):
def afficheresultats(occurences):
def signaleErreur():
def videEntree():

def setStop(self):
"""Trip the stop flag."""
stop = True

def run():
	processus.start()


stop=False
processus=threading.Thread(target=RunAll)

fenetre=Tk()
fenetre.title("LoTo SaKieBon : loto simple à 6 numéros")

#Creation du champ d'entree et de son texte
texte=Label(fenetre,text="Nombre de grilles à générer :",font="Arial 10 bold" )
texte.grid(row=1,padx=10,pady=5)
entree=Entry(fenetre,bg="grey")
entree.insert(0,"3000")
entree.grid(row=2,padx=10)

#Ce texte sera modifié par la suite pour afficher l'etat du tirage
texte2=Label(fenetre,text= "Grilles generées :",font="Arial 10 bold")
texte2.grid(row=4,padx=5,pady=5)

#Ce texte sera modifié par la suite pour afficher l'etat de la recherche d'occurence
texte3=Label(fenetre,text= "Recherche d'occurence :",font="Arial 10 bold")
texte3.grid(row=5,padx=5,pady=5)

#Ce texte sera modifié par la suite pour afficher les resultats
texte4=Label(fenetre,text= "Resultats :",font="Arial 10 bold")
texte4.grid(row=6,padx=5,pady=5)

#le Bouton unique qui declenche tout
Button(fenetre,text="Lancer la recherche d'occurences",font="Arial 10 bold",fg="black",bg="yellow",command=run).grid(row=3,padx=5,pady=10)

#creation d'un canevas pour y mettre deux images
can=Canvas(fenetre,width=120,height=150,bg="black")
photo=PhotoImage(file="panther.GIF")
photo2=PhotoImage(file="foraef.GIF")
item=can.create_image(60,60,image=photo)
item2=can.create_image(60,135,image=photo2)
can.grid(row=1,column=1,rowspan=6,padx=5,pady=15)

#demarage de la boucle d'evenements
fenetre.mainloop()

Ensuite il te reste plus qu'a assigné la fonction setStop a un bouton ou evenment.

Lien vers le commentaire
Partager sur d’autres sites

:-D pour tes reponses :francais:

au fait mon programme ressemble a ça quand il tourne...

apres 20h de calcul ça donne ça

lotosakiebonv0213rk.jpg

je souhaiterais egalement ajouter un chronometre qui enregistre le temps qu'a mis le prog pour faire son boulot

au fait quand tu parle de " l'utilisation des arbres d'objets de python " , tu veux dire l'utilisation des classes ? si c'est ça alors sisi jai apris (vaguement en fait), c'est justement ce pdf que tu m'as mis en lien qui ma permis de debuter python j'en suis au chapitre 15 (page 227) ou les choses devienent interessentes

j'ai pas utilisé les classes parsque j'en ai pas vu l'interet dans mon prog...et vu que c'est mon 1er vrai projet...j'ai construit le programme morceau par morceau comme l'a indiqué le pdf (faire un ptit truc , le tester, ajouter un truc , tester , ajouter un truc ,tester...etc...) c'est dans cette philosophie que j'en suis arrivé aux definitions et il est vrai que vu l'ampleur que commence a prendre le prog je vais realiser une refonte du code pour transformer en classe (vu que je compte la deriver en EuroMillion et autres jeux de hasard :p )

Lien vers le commentaire
Partager sur d’autres sites

Je ne pense pas, psyco ert surtout a accelerer le demarrage a froid d'une application python, car comme tout langage interpreté la ou tu perd le plus est lors du lancement de l'application quand il doit compiler le script python pour en faire du langage machine, et psyco est fais pour cela. Tu peux toujours essayer =) si suffit juste d'importer le module psyco au debut de ton prog.

Lien vers le commentaire
Partager sur d’autres sites

aarghh , non ta manip n'arrete pas le thread , au contraire elle fait tourner le prog en boucle...pas cool

jvais voir pour un autre truc

edit : ha si cest bon cest ça , je n'ai qu'a mettre une 2eme condition pour demarer a chaque fois le prog :transpi:

ça correspond a sque t'a dit plus haut "and mon_autre_condition'

jvais verifier ça de suite

Lien vers le commentaire
Partager sur d’autres sites

cest bizarre le fonctionement

je lance le prog , le thread est lancé , le prog tourne en boucle , j'appuie sur stop ,je sors de la boucle et.....oui....comment faire pour relancer une nouvelle recherche sans rappeler le thread (car ça me colle une erreur " le thread est deja lancé"....)

edit : a partir du moment ou je sors de la boucle, pas moyen de relancer le prog....il faudrait que je reste en attente (d'un evenement, d'un clic) dans la boucle...

Lien vers le commentaire
Partager sur d’autres sites

C'est bizarre en fouillant un peu sur le net je tombe sur la meme explication que je t'ai donné a partir du moment ou il est sorti de la boucle run le thread est mort:

	import threading
import time

class ThreadOne ( threading.Thread ):

   def run ( self ):

	  print 'Thread', self.getName(), 'started.'
	  time.sleep ( 5 )
	  print 'Thread', self.getName(), 'ended.'

class ThreadTwo ( threading.Thread ):

   def run ( self ):

	  print 'Thread', self.getName(), 'started.'
	  thingOne.join()
	  print 'Thread', self.getName(), 'ended.'

thingOne = ThreadOne()
thingOne.start()
thingTwo = ThreadTwo()
thingTwo.start()

http://www.devshed.com/c/a/Python/Basic-Th...ng-in-Python/3/

Par contre il est vrai qu'il me semble avir rencontré le meme probleme que toi à l'epoque ou je m'etait penché sur le sujet et que le seul moyen d'avoir un truc qui marche et propre et surtout qui me permettait de lancer plusieurs processus en parallele etait d'utiliser Threading.thread dans une classe comme ici (dans le premier exemple aussi que je te donne il l'utilise dans une classe):

class diskjockey(threading.Thread):
def __init__(self,mp3_player,jukebox):
 threading.Thread.__init__(self)
 self.mp3player=mp3_player
 self.jukebox=jukebox
 self.session_pid=0
 self.stopped=0
 #signal.signal(signal.SIGTERM,self.sighandler)
def run(self):
 while self.stopped==0:
a=9
#print "test"

def main():
my_conf=config()
new_pid=0
pid=os.fork()
if pid == 0:
 signal.signal(signal.SIGTERM,sighandler)
 os.setsid()
 stop=0
 player1=mplayer('/usr/bin/mpg123')
 pyrasdb=xmldb(my_conf)
 pyrasdb.parse()
 pyrasdb.file_to_mem()
 juke=jukebox(my_conf,pyrasdb)
 juke.start()

 disco_stu=diskjockey(player1,juke)
 disco_stu.start()
 while 1:
  print "o"

else:
 sys.exit(0)

Courage on est tous passer par la, mais une fois que tu a ton code pour faire un truc tu pourrai le reutiliser autant que tu veux =)

Lien vers le commentaire
Partager sur d’autres sites

:-D tsubasaleguedin

je suis sur la voie de la verité, oui je VOIS :roll: ....la drogue caymal :mad2:

nan sans dec , jai reussi avec l'aide de docs sur le net et de l'acharnement perso a creer un thread , a le stoper , puis a le relancer :byebye:

je commente le script et jte le montre...

par contre j'utilise toujours pas les classes :eeek2:

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...