<p class="spip">Dans le <a href="http://www.coagul.org/article.php3?id_article=433" class="spip_out">tutoriel précédent</a>, 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 <a href="http://www.coagul.org/article.php3?id_article=423" class="spip_out">tutoriel 5</a>.</p>

<h3>Éléments abordés dans ce document</h3>
<li> L’evaluation d’expression « avec eval() »
<br /><li> Les afficheurs LCD de QT « avec display() »
<br /><li> L’affichage de boîte de dialogue « avec QMessageBox.information() »
<br /><li> Des propriétés supplémentaires associées aux widgets QT « avec setReadOnly(), setFocus() »
<br /><li> Le module time « avec time() »
<h3>Au travail</h3>
<p class="spip">On rajoute la fonction <strong class="spip">NouveauNombres()</strong> à 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.</p>

<p class="spip">Cette fonction sera appelée une première fois par la fonction <strong class="spip">StartSlot()</strong> et ensuite par la fonction <strong class="spip">TestReponseSlot()</strong> jusqu’à la fin de l’exercice.</p>

<p class="spip">La fonction <strong class="spip">StartSlot()</strong> 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.</p>

<p class="spip">La fonction <strong class="spip">TestReponseSlot()</strong> 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é.</p>

<p class="spip">Ce qui nous donne le code suivant :</p>
<div style='text-align: left;' class='spip_code' dir='ltr'><code><br />
class MainForm_Impl(MainForm):<br />
    op1=0                        #la valeur du 1er opérande<br />
    op2=0                        #la valeur du 2nd opérande<br />
    resultat=0                  #la valeur du résultat<br />
    debutExercice=0.0   #pour calculer la durée de l'exercice<br />
<br />
    def __init__(self,parent = None,name = None,modal = 0,fl = 0):<br />
        MainForm.__init__(self,parent,name,modal,fl)<br />
<br />
        self.timer=QTimer(self)<br />
        self.connect(self.timer, SIGNAL('timeout()'), self.TimeOutSlot)<br />
<br />
# public slot<br />
<br />
    def init(self):<br />
        items=[]<br />
        items.append(QListViewItem(self.ExerciseListView,"Additions"))<br />
        items.append(QListViewItem(self.ExerciseListView,"Divisions"))<br />
        items.append(QListViewItem(self.ExerciseListView,"Multiplications"))<br />
        items.append(QListViewItem(self.ExerciseListView,"Soustractions"))<br />
<br />
        try:<br />
            fsock = open('exercices.txt')<br />
            try:<br />
                dataLines = [line for line in fsock.readlines() if line[0]!='#']<br />
            finally:<br />
                fsock.close()<br />
        except IOError:<br />
            pass<br />
        try:<br />
            for dataLine in dataLines:<br />
                exercice, oorq, delai, question = re.findall("^([^\\t]+)\\t+([^\\t]+)\\t+(\\d+)\\t+(\\d+)",dataLine)[0]<br />
                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]<br />
                items.append(QListViewItem(items[['+', '/', '*', '-'].index(operateur)], unicode(exercice,'utf8'), oorq, delai, question))<br />
        except NameError:<br />
            pass<br />
<br />
<br />
    def TestReponseSlot(self):<br />
        if self.timer.isActive(): self.timer.stop()<br />
        <br />
        if self.operande1LineEdit.text().ascii()==''     \<br />
        or self.operande2LineEdit.text().ascii()==''   \<br />
        or self.resultatLineEdit.text().ascii()==''         \<br />
        or eval(self.operande1LineEdit.text().ascii()+self.operateur.text().ascii()+self.operande2LineEdit.text().ascii()) <> eval(self.resultatLineEdit.text().ascii()):<br />
            self.WrongLCDNumber.display(self.WrongLCDNumber.intValue()+1)<br />
            QMessageBox.information(self,'', unicode('Voici la bonne rÃ©ponse :\n'+`self.op1`+' '+self.operateur.text().ascii()+' '+`self.op2`+' = '+`self.resultat`,'utf8'))<br />
            #TODO : mÃ©moriser les paramÃ¨tre de la question pour la reposer Ã  la fin de l'exercice<br />
        else:<br />
            self.GoodLCDNumber.display(self.GoodLCDNumber.intValue()+1)<br />
        self.TotalLCDNumber.display(self.TotalLCDNumber.intValue()+1)<br />
<br />
        if self.TotalLCDNumber.intValue() >= int(self.CountLineEdit.text().ascii()) or not NouveauxNombres(self):<br />
            self.StartPushButton.setEnabled(1)<br />
            QMessageBox.information(self,'', unicode('Exercice terminé en %d secondes' % int(time.time()-self.debutExercice),'utf8'))<br />
        else:<br />
            self.DelaiProgressBar.setProgress(int(self.DelaiLineEdit.text().ascii())*100)<br />
            self.timer.start(10)<br />
<br />
    def StartSlot(self):<br />
        self.StartPushButton.setEnabled(False)<br />
        NouveauxNombres(self)<br />
        self.DelaiProgressBar.setTotalSteps(int(self.DelaiLineEdit.text().ascii())*100)<br />
        self.DelaiProgressBar.setProgress(int(self.DelaiLineEdit.text().ascii())*100)<br />
        self.operateur.setText(['*', '+', '-', '/'][self.OperateurComboBox.currentItem()])<br />
        self.TotalLCDNumber.display(0)<br />
        self.GoodLCDNumber.display(0)<br />
        self.WrongLCDNumber.display(0)<br />
        self.timer.start(10)<br />
        self.debutExercice=time.time()<br />
<br />
    def TimeOutSlot(self):<br />
        p = self.DelaiProgressBar.progress()<br />
        if  p > 0 :<br />
            self.DelaiProgressBar.setProgress(p-1)<br />
        else:<br />
            self.TestReponseSlot()<br />
 <br />
    def SelectExerciseSlot(self):<br />
        exercise=self.ExerciseListView.currentItem().text(1).ascii()<br />
        if exercise:<br />
            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]<br />
            self.MinOp1LineEdit.setText(op1Min)<br />
            self.MaxOp1LineEdit.setText(op1Max)<br />
            self.OperateurComboBox.setCurrentItem(['*', '+', '-', '/'].index(operateur))<br />
            self.MinOp2LineEdit.setText(op2Min)<br />
            self.MaxOp2LineEdit.setText(op2Max)<br />
            self.ResultatMaxLineEdit.setText(max)<br />
            self.PositionLineEdit.setText(`(q1=='_')+(q2=='_')*2+(q3=='_')*4`)<br />
            self.CountLineEdit.setText(self.ExerciseListView.currentItem().text(3).ascii())<br />
            self.DelaiLineEdit.setText(self.ExerciseListView.currentItem().text(2).ascii())<br />
        else:<br />
            operateur=self.ExerciseListView.currentItem().text(0).ascii()<br />
            self.OperateurComboBox.setCurrentItem(['Multiplications', 'Additions', 'Soustractions', 'Divisions'].index(operateur))<br />
    <br />
def NouveauxNombres(self, revision=0):<br />
    "Initialise les donnÃ©es pour une nouvelle question."<br />
    op1min=int(self.MinOp1LineEdit.text().ascii())<br />
    op1max=int(self.MaxOp1LineEdit.text().ascii())<br />
    op2min=int(self.MinOp2LineEdit.text().ascii())<br />
    op2max=int(self.MaxOp2LineEdit.text().ascii())<br />
    resultatMax=int(self.ResultatMaxLineEdit.text().ascii())<br />
    operation=('*', '+', '-', '/')[self.OperateurComboBox.currentItem()]<br />
    posQuestion=int(self.PositionLineEdit.text().ascii())<br />
    <br />
    if revision:<br />
        QMessageBox.information( 0, "Révision", "Révisions terminées")<br />
        return 0<br />
    else:<br />
        if operation=='/':<br />
            while 1:<br />
                self.op2 = random.randint(op2min, op2max)<br />
                self.resultat = random.randint(0,resultatMax)<br />
                self.op1 = self.resultat*self.op2<br />
                if self.op1>=op1min and self.op1 <= op1max: break<br />
        else:<br />
            while 1:<br />
                self.op1 = random.randint(op1min, op1max)<br />
                self.op2 = random.randint(op2min, op2max)<br />
                self.resultat = eval(str(self.op1) + operation + str(self.op2))<br />
                if self.resultat>=0 and self.resultat <= resultatMax: break<br />
<br />
    if posQuestion == 1:            posTrou=0<br />
    elif posQuestion == 2:        posTrou=1<br />
    elif posQuestion == 3:        posTrou=random.randint(0,1)<br />
    elif posQuestion == 4:        posTrou=2<br />
    elif posQuestion == 5:        <br />
        if random.randint(0,1):posTrou=2 <br />
        else:                              posTrou=0<br />
    elif posQuestion == 6:        posTrou=random.randint(1,2)<br />
    elif posQuestion == 7:        posTrou=random.randint(0,2)<br />
<br />
    if posTrou==0:            # op1<br />
        self.operande1LineEdit.setText("")<br />
        self.operande1LineEdit.setReadOnly(0)<br />
        self.operande2LineEdit.setText(`self.op2`)<br />
        self.operande2LineEdit.setReadOnly(1)<br />
        self.resultatLineEdit.setText(`self.resultat`)<br />
        self.resultatLineEdit.setReadOnly(1)<br />
        self.operande1LineEdit.setFocus()<br />
    elif posTrou==1:            # op2<br />
        self.operande1LineEdit.setText(`self.op1`)<br />
        self.operande1LineEdit.setReadOnly(1)<br />
        self.operande2LineEdit.setText("")<br />
        self.operande2LineEdit.setReadOnly(0)<br />
        self.resultatLineEdit.setText(`self.resultat`)<br />
        self.resultatLineEdit.setReadOnly(1)<br />
        self.operande2LineEdit.setFocus()<br />
    elif posTrou==2:    #resultat<br />
        self.operande1LineEdit.setText(`self.op1`)<br />
        self.operande1LineEdit.setReadOnly(1)<br />
        self.operande2LineEdit.setText(`self.op2`)<br />
        self.operande2LineEdit.setReadOnly(1)<br />
        self.resultatLineEdit.setText("")<br />
        self.resultatLineEdit.setReadOnly(0)<br />
        self.resultatLineEdit.setFocus()    <br />
    return 1<br />
</code></div>
<p class="spip">Si vous lancez l’application, vous devriez obtenir ceci :
<span class='spip_document_829 spip_documents spip_documents_center' >
<img src='http://download.tuxfamily.org/assocoagul/drupal-files/spip/revcal.jpg' width="459" height="426" alt="" /></span><p>

<p class="spip"><a href="http://www.coagul.org/article.php3?id_article=437" class="spip_out">Pour la suite, c’est ici</a></p>

<h2>Historique des modifications</h2>
<table class="spip">
<thead><tr class='row_first'><th scope='col'><strong class="spip">Version</strong></th><th scope='col'><strong class="spip">Date</strong></th><th scope='col'><strong class="spip">Commentaire</strong></th></tr></thead>
<tbody>
<tr class="row_even"><td>0.1</td><td>03/04/2006</td><td>Création par Jibux</td></tr>
<tr class="row_odd"><td>0.2</td><td>26/11/2006</td><td>Ajout d’un lien vers l’article suivant</td></tr>
</tbody>
</table>
<dl class='spip_document_831 spip_documents spip_documents_center' >
<dt><a href="http://download.tuxfamily.org/assocoagul/drupal-files/spip/Archive-2.zip" title='Zip - 45 ko' type="application/zip"><img src='dist/vignettes/zip.png' width='52' height='52' alt='Zip - 45 ko' /></a><dt>
<dt class='spip_doc_titre' style='width:120px;'><strong>Les fichiers sources de cette application</strong></dt>
</dl>