Projet

Général

Profil

Développement du module Ordre alphabétique 1

Dans ce module, il s'agit de ranger des mots dans l'ordre alphabétique. Pour ce faire, on dispose d'une "Aire de jeu" sur laquelle on trouve des cases dans lesquelles on peut déposer des étiquettes par cliquer-déposer (Drag and drop).

Attendus pédagogiques

  • Les mots pourront être choisis aléatoirement dans une liste fournie avec le logiciel en fonction de critères tels que nature, niveaux (CP, CE1...), mots outils et en fonction du nombre de lettres communes possibles en début de mot.
  • Il sera aussi possible de choisir ces mots dans une liste de mots extraits du texte de l'exercice.
  • L'exercice ne pourra être évalué que lorsque tous les mots auront été placés dans les cases.
  • L'exercice ne sera achevé que lorsque tous les mots seront bien placés.
Lors du clic sur le bouton vérifier, un retour visuel est fourni :
  • Les étiquettes en orange (pour l'instant) forment la plus longue liste dans l'ordre alphabétique
  • Les étiquettes en rouge (toujours pour l'instant) sont mal placées (dans l'ordre alphabétique)
  • Les cases contenant une étiquette bien placée (le xième mot de la liste est bien sur la case x) sont en vert.

Il n'y a pas d'évaluation si toutes les étiquettes ne sont pas placées dans une case.
On ne passe à l'exercice suivant que lorsque les étiquettes sont toutes bien placées.

Architecture du module

Comme tous les modules, celui-ci hérite de AbulEduCommonStatesV1, de plus il hérite aussi de AbulEduOutilsV1 qui fourni un ensemble de fonctionnalités comme le tri, et la vérification de l'ordre des étiquettes.
Cet exercice est un enfant de la page d'accueil sur laquelle se superposeront les widget AbulEduExerciceWidgetAireDeTravail et AbulEduExerciceWidgetTelecommande

Création de l'exercice

dans la MainWindow avec gv_Accueil le décor de l'exercice (AbuleduPageAccueilV1)

        ExerciceOrdreAlpha1 *b = new ExerciceOrdreAlpha1(gv_Accueil);
        connect(b, SIGNAL(exerciceExited()), this, SLOT(on_exerciceExited()));
        gv_Accueil->abePageAccueilDesactiveZones(true);
        gv_Accueil->abePageAccueilGetMenu()->hide();

  • ligne 2 La mainWindow est connectée au signal exerciceExited()emis par l'exercice lors de sa destruction
  • ligne 3 et 4 On désactive les zones sensibles de la page d'accueil et on masque le menu graphique.

Construction de l'exercice

L'exercice doit être connecté au signal dimensionsChangees() émis par la page d'accueil lorsque ses dimensions sont modifiées. Cette façon de faire va éviter des appels inutiles aux fonctions de redimensionnement.

    connect(m_parent, SIGNAL(dimensionsChangees()),this, SLOT(setDimensionsWidgets()));

Dans cet exercice, l'utilisateur va devoir déplacer des étiquettes-mots et les déposer dans la bonne case : c'est la classe AbulEduEtiquettesV1 qui répond à cet usage.
Les étiquettes-mots seront des AbulEduPieceV1 et les cases des AbulEduCellulesV1 disposées judicieusement sur une QGraphicsView fournie par AbulEduEtiquettesV1

    gv_AireDeJeu = new AbulEduEtiquettesV1(QPointF(0,0));    
    proxy = getAbeExerciceAireDeTravailV1()->ui->gvPrincipale->scene()->addWidget(gv_AireDeJeu); // le proxy va permettre de modifier l'ordre d'affichage des objets
    proxy->setZValue(-1); // gv_AireDeJeu sera en dessous des autres objets
    gv_AireDeJeu->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    gv_AireDeJeu->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    gv_AireDeJeu->setStyleSheet("background-color: rgba(0,0,0,0)"); // Fond transparent   
    gv_AireDeJeu->setFrameShape(QFrame::NoFrame);
    m_scene = gv_AireDeJeu->scene();
    setDimensionWidgets();
    sequenceMachine->start();

  • Ligne 1, On crée le widget (QGraphicsView) sur lequel seront déposés les étiquettes et les cases
  • Lignes 2 et 3, gv8aireDejeu est intégrée à la QGraphicsView gvPrincipale du Widget AbulEduExerciceWidgetAireDeTravail, l'utilisation du QGraphicsProxyWidget va permettre (entre autre) de modifier l'ordre d'affichage des objets de la QGraphicsView (setZValue).
  • Lignes 4 et 5, On n'affiche pas les ascenseurs.
  • Ligne 6 On met un fond transparent, ce qui permet de voir le graphisme sous-jacent.
  • Ligne 7, On enlève la bordure du widget
  • Ligne 9, On redimensionne le tout
  • Ligne 10, On démarre l'exercice par le biais de la AbulEduStateMachineV1

Construction des étiquettes-mots et des Cellules

Le slot ExerciceOrdreAlpha1::slotInitQuestionEntered() crée la liste des mots dont nous aurons besoin pour l'exercice.
La fonction afficheMots(); va créer les étiquettes et les cellules destinées à les accueillir.

Dans un premier temps, il faut calculer la taille des étiquettes

    clearScene();

    qreal hauteurEtiquette= 0 ; // hauteur des étiquettes
    maxLargeurEtiquette = 0; // Taille maximum des étiquettes créées
    for(int i = 0; i<m_listeMots.size(); i++)
    {
        QFontMetrics metric(QFont("LiberationSans",14));
        QSize size = QSize((metric.boundingRect(m_listeMots[i])).width(),
                           (metric.boundingRect(m_listeMots[i])).height());
        hauteurEtiquette = size.height() + 10;
        maxLargeurEtiquette=qMax(maxLargeurEtiquette, size.width()+10);
    }
    maxLargeurEtiquette = maxLargeurEtiquette + 20;

Pour cela on utilise l'objet QFontMetrics metric qui apporte tout un tas d'informations utiles sur la font passée en argument. Il permet dans ce cas de calculer les dimensions du bounding rectangle entourant le texte passé en argument (ligne 8).

Puis, on crée les étiquetets-mots :

    if(m_listeMots.size()>0)
    {
        // Création des étiquettes
        for(int i=0;i<m_listeMots.size();i++)
        {
            AbulEduPieceV1 *etiq = new AbulEduPieceV1(QSize(maxLargeurEtiquette, hauteurEtiquette));
            etiq->abePieceSetFont(QFont("LiberationSans",14));
            etiq->abePieceSetTexte(m_listeMots[i]); // Le texte visible de l'étiquette
            etiq->setObjectName(QString::number(i));
            etiq->setBrush(gradient);  // La brosse de fond de l'étiquette
            etiq->abePieceSetMarge(5);
            etiq->abePiecePlaceFixe(false); // Le déplacement des étiquettes est libre sur l'aire de jeu
            etiq->abePieceSetTexteAlignement(Qt::AlignCenter);
            etiq->setParent(gv_AireDeJeu->scene());
            gv_AireDeJeu->scene()->addItem(etiq);
            m_listeEtiquettes.append(etiq); // Fait la liste des étiquettes
        }
        placeMots();
Le code étant "autodocumenté, je ne commente que les lignes importantes :P :
  • Ligne 9 On attribue le numéro de l'étiquette (dans l'ordre alphabétique) comme nom de l'objet créé, ceci permettra de comparer les listes par la suite.
  • Ligne 14 Il est nécessaire de parenter les étiquettes à la scene de l'aire de jeu gv_AireDeJeu->scene()
  • Ligne 15 L'étiquette est placée sur la GraphicsView.

La dernière ligne place les étiquettes de manière aléatoire dans la moitié inférieure de l'aire de jeu en évitant qu'elles se chevauchent.

Puis on crée les cellules devant accueillir les étiquettes-mots.

 for(int i=0;i<m_listeMots.size();i++){
        AbulEduCelluleV1 *zone=new AbulEduCelluleV1(QSizeF(maxLargeurEtiquette + 10, hauteurEtiquette +10));
        zone->setObjectName(QString::number(i));
        zone->setParent(gv_AireDeJeu->scene());
        gv_AireDeJeu->scene()->addItem(zone);
        m_listeCellules.append(zone);
    }
    placeCellules();

Les lignes à ne pas rater sont les lignes 3 et 4 qui reprennent le même principe que les étiquettes.
h2. A venir...

Redmine Appliance - Powered by TurnKey Linux