Python et QT (tutoriel 7)
Dans le tutoriel précédent, nous avons révisé nos connaissances sur l’IDE Eric en créant une petite application qui manipulait une barre de progression avec un timer. Nous allons utiliser ces élements pour compléter l’application que nous avons commencé dans le tutoriel 5.
Éléments abordés dans ce document
Au travail
On rajoute la fonction NouveauNombres() à notre classe MainForm_Impl. Celle-ci va tirer des nombres au hasard en respectant les limites imposées pour l’exercice. Elle se charge également de l’affichage et des modifications des zones de saisie.
Cette fonction sera appelée une première fois par la fonction StartSlot() et ensuite par la fonction TestReponseSlot() jusqu’à la fin de l’exercice.
La fonction StartSlot() est appelée lorsque l’utilisateur clique sur le bouton qui permet de commencer l’exercice. Elle est chargée d’initialiser les paramètres liés à l’exercice et notamment le timer qui va rythmer le tout.
La fonction TestReponseSlot() est appelée à chaque fois que l’utilisateur valide une réponse ou lorsque la barre de progression arrive à 0. Elle vérifie la réponse, met à jour les compteurs et relance une nouvelle question si l’exercice n’est pas terminé.
Ce qui nous donne le code suivant :
class MainForm_Impl(MainForm):
op1=0 #la valeur du 1er opérande
op2=0 #la valeur du 2nd opérande
resultat=0 #la valeur du résultat
debutExercice=0.0 #pour calculer la durée de l'exercice
def __init__(self,parent = None,name = None,modal = 0,fl = 0):
MainForm.__init__(self,parent,name,modal,fl)
self.timer=QTimer(self)
self.connect(self.timer, SIGNAL('timeout()'), self.TimeOutSlot)
# public slot
def init(self):
items=[]
items.append(QListViewItem(self.ExerciseListView,"Additions"))
items.append(QListViewItem(self.ExerciseListView,"Divisions"))
items.append(QListViewItem(self.ExerciseListView,"Multiplications"))
items.append(QListViewItem(self.ExerciseListView,"Soustractions"))
try:
fsock = open('exercices.txt')
try:
dataLines = [line for line in fsock.readlines() if line[0]!='#']
finally:
fsock.close()
except IOError:
pass
try:
for dataLine in dataLines:
exercice, oorq, delai, question = re.findall("^([^\\t]+)\\t+([^\\t]+)\\t+(\\d+)\\t+(\\d+)",dataLine)[0]
op1Min, op1Max, q1, operateur, op2Min, op2Max, q2, max, q3 = re.findall("^\\[([0-9]{1,3})..([0-9]{1,3})\\](_?)([+\\-*/])\\[([0-9]{1,3})..([0-9]{1,3})\\](_?)<=([0-9]{1,3})(_?)$", oorq)[0]
items.append(QListViewItem(items[['+', '/', '*', '-'].index(operateur)], unicode(exercice,'utf8'), oorq, delai, question))
except NameError:
pass
def TestReponseSlot(self):
if self.timer.isActive(): self.timer.stop()
if self.operande1LineEdit.text().ascii()=='' \
or self.operande2LineEdit.text().ascii()=='' \
or self.resultatLineEdit.text().ascii()=='' \
or eval(self.operande1LineEdit.text().ascii()+self.operateur.text().ascii()+self.operande2LineEdit.text().ascii()) <> eval(self.resultatLineEdit.text().ascii()):
self.WrongLCDNumber.display(self.WrongLCDNumber.intValue()+1)
QMessageBox.information(self,'', unicode('Voici la bonne réponse :\n'+`self.op1`+' '+self.operateur.text().ascii()+' '+`self.op2`+' = '+`self.resultat`,'utf8'))
#TODO : mémoriser les paramètre de la question pour la reposer à la fin de l'exercice
else:
self.GoodLCDNumber.display(self.GoodLCDNumber.intValue()+1)
self.TotalLCDNumber.display(self.TotalLCDNumber.intValue()+1)
if self.TotalLCDNumber.intValue() >= int(self.CountLineEdit.text().ascii()) or not NouveauxNombres(self):
self.StartPushButton.setEnabled(1)
QMessageBox.information(self,'', unicode('Exercice terminé en %d secondes' % int(time.time()-self.debutExercice),'utf8'))
else:
self.DelaiProgressBar.setProgress(int(self.DelaiLineEdit.text().ascii())*100)
self.timer.start(10)
def StartSlot(self):
self.StartPushButton.setEnabled(False)
NouveauxNombres(self)
self.DelaiProgressBar.setTotalSteps(int(self.DelaiLineEdit.text().ascii())*100)
self.DelaiProgressBar.setProgress(int(self.DelaiLineEdit.text().ascii())*100)
self.operateur.setText(['*', '+', '-', '/'][self.OperateurComboBox.currentItem()])
self.TotalLCDNumber.display(0)
self.GoodLCDNumber.display(0)
self.WrongLCDNumber.display(0)
self.timer.start(10)
self.debutExercice=time.time()
def TimeOutSlot(self):
p = self.DelaiProgressBar.progress()
if p > 0 :
self.DelaiProgressBar.setProgress(p-1)
else:
self.TestReponseSlot()
def SelectExerciseSlot(self):
exercise=self.ExerciseListView.currentItem().text(1).ascii()
if exercise:
op1Min, op1Max, q1, operateur, op2Min, op2Max, q2, max, q3 = re.findall("^\\[([0-9]{1,3})..([0-9]{1,3})\\](_?)([+\\-*/])\\[([0-9]{1,3})..([0-9]{1,3})\\](_?)<=([0-9]{1,3})(_?)$", exercise)[0]
self.MinOp1LineEdit.setText(op1Min)
self.MaxOp1LineEdit.setText(op1Max)
self.OperateurComboBox.setCurrentItem(['*', '+', '-', '/'].index(operateur))
self.MinOp2LineEdit.setText(op2Min)
self.MaxOp2LineEdit.setText(op2Max)
self.ResultatMaxLineEdit.setText(max)
self.PositionLineEdit.setText(`(q1=='_')+(q2=='_')*2+(q3=='_')*4`)
self.CountLineEdit.setText(self.ExerciseListView.currentItem().text(3).ascii())
self.DelaiLineEdit.setText(self.ExerciseListView.currentItem().text(2).ascii())
else:
operateur=self.ExerciseListView.currentItem().text(0).ascii()
self.OperateurComboBox.setCurrentItem(['Multiplications', 'Additions', 'Soustractions', 'Divisions'].index(operateur))
def NouveauxNombres(self, revision=0):
"Initialise les données pour une nouvelle question."
op1min=int(self.MinOp1LineEdit.text().ascii())
op1max=int(self.MaxOp1LineEdit.text().ascii())
op2min=int(self.MinOp2LineEdit.text().ascii())
op2max=int(self.MaxOp2LineEdit.text().ascii())
resultatMax=int(self.ResultatMaxLineEdit.text().ascii())
operation=('*', '+', '-', '/')[self.OperateurComboBox.currentItem()]
posQuestion=int(self.PositionLineEdit.text().ascii())
if revision:
QMessageBox.information( 0, "Révision", "Révisions terminées")
return 0
else:
if operation=='/':
while 1:
self.op2 = random.randint(op2min, op2max)
self.resultat = random.randint(0,resultatMax)
self.op1 = self.resultat*self.op2
if self.op1>=op1min and self.op1 <= op1max: break
else:
while 1:
self.op1 = random.randint(op1min, op1max)
self.op2 = random.randint(op2min, op2max)
self.resultat = eval(str(self.op1) + operation + str(self.op2))
if self.resultat>=0 and self.resultat <= resultatMax: break
if posQuestion == 1: posTrou=0
elif posQuestion == 2: posTrou=1
elif posQuestion == 3: posTrou=random.randint(0,1)
elif posQuestion == 4: posTrou=2
elif posQuestion == 5:
if random.randint(0,1):posTrou=2
else: posTrou=0
elif posQuestion == 6: posTrou=random.randint(1,2)
elif posQuestion == 7: posTrou=random.randint(0,2)
if posTrou==0: # op1
self.operande1LineEdit.setText("")
self.operande1LineEdit.setReadOnly(0)
self.operande2LineEdit.setText(`self.op2`)
self.operande2LineEdit.setReadOnly(1)
self.resultatLineEdit.setText(`self.resultat`)
self.resultatLineEdit.setReadOnly(1)
self.operande1LineEdit.setFocus()
elif posTrou==1: # op2
self.operande1LineEdit.setText(`self.op1`)
self.operande1LineEdit.setReadOnly(1)
self.operande2LineEdit.setText("")
self.operande2LineEdit.setReadOnly(0)
self.resultatLineEdit.setText(`self.resultat`)
self.resultatLineEdit.setReadOnly(1)
self.operande2LineEdit.setFocus()
elif posTrou==2: #resultat
self.operande1LineEdit.setText(`self.op1`)
self.operande1LineEdit.setReadOnly(1)
self.operande2LineEdit.setText(`self.op2`)
self.operande2LineEdit.setReadOnly(1)
self.resultatLineEdit.setText("")
self.resultatLineEdit.setReadOnly(0)
self.resultatLineEdit.setFocus()
return 1
Si vous lancez l’application, vous devriez obtenir ceci :

Historique des modifications
| Version | Date | Commentaire |
|---|---|---|
| 0.1 | 03/04/2006 | Création par Jibux |
| 0.2 | 26/11/2006 | Ajout d’un lien vers l’article suivant |
| Fichier attaché | Taille |
|---|---|
| revcal.jpg | 28.2 Ko |
| Les fichiers sources de cette application | 45 Ko |


Commentaires
> Python et QT (tutoriel 7)
Merci pour ta relecture
> Python et QT (tutoriel 7)
RAS :o)