Deux points libres A et B et tracé de la droite (AB)

Il s'agit dans cet exemple de créer deux points A et B qu'on peut déplacer à l'aide de la souris puis de tracer la droite (AB) correspondante.

pdrt.pnf

Répertoire : pdrt. Trois fichiers sont utilisés : main.cpp, fenetre.h et fenetre.cpp.

main.cpp

#include <QApplication>

#include "fenetre.h"

int main (int argc, char *argv []) {
     QApplication app (argc, argv);
     Fenetre f;
     f.show();
     return app.exec ();
}

On crée l'application app, le fenêtre principale f puis on lance la boucle d'exécution app.

fenetre.h

#ifndef FENETRE_H
#define FENETRE_H

#include <QWidget>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QPainter>

On déclare les objets de la bibiliothèque Qt nécessaires. On peut écrire directement #include <QtGui>. Seuls les objets utiles seront annexés.

#include "geo2D/point_libre.h"
#include "geo2D/droite.h"
//#include "geo2D/geo2D.h"

On déclare les objets de la bibliothèque geo2D nécessaires.On peut écrire directement #include "geo2D/geo2D.h" mais dans ce cas tous les objets de la bibliothèque geo2Dseront ajoutés au programme qui sera donc plus gros.

class Fenetre: public QWidget {

    Q_OBJECT

Il s'agit de la déclaration d'une macro nécessaire, entre autres, à l'installation des fonctions gérant des évenements comme les mouvements de la souris.

public:
    repere *R;
    point_libre *A;
    point_libre *B;
    droite *AB;

On déclare ici tous les objets géométriques qui seront utilisés.

    bool presse;

Indicateur signalant qu'il y a un déplacement en cours

    Fenetre (QWidget *parent = 0);

protected:
    void paintEvent (QPaintEvent *);
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

};

#endif

On définit ici les quatre fonctions gérant le dessin et l'action de la souris (appui sur le bouton, déplacement, relâchement).

fenetre.cpp

/*
 * pdrt
 *
 */

#include "fenetre.h"

Fenetre::Fenetre (QWidget *parent): QWidget (parent) {
    setGeometry (0, 0, 600, 450);
    setMouseTracking (true);
    setCursor (Qt::ArrowCursor);
    presse = false;

Constructeur de la fenêtre principale : on indique sa taille, on donne la possibilité de gérer le déplacement de la souris sans qu'on ait besoin d'appuyer sur le bouton (setMouseTracking (true);), on fixe le curseur par défaut puis on initialise l'indicateur de déplacement des points libres.

    R = new repere (300, 225, 600, 450, 50.0, 1.0);
    A = new point_libre (3.0, 2.0, "A", R);
    B = new point_libre (3.0, -2.0, "B", R);
    AB = new droite (A, B, NULL, R);
 }

On crée ici les objets géométriques, le repère, les points deplaçables à la souris et la droite (AB).

void Fenetre::paintEvent (QPaintEvent *) {
    setPalette (QPalette (QColor (255, 255, 255)));
    setAutoFillBackground (true);
    QPainter painter (this);
    painter.setPen (Qt::red);
    (*R).trace (&painter);
    painter.setPen (Qt::blue);
    (*A).trace (&painter);
    (*B).trace (&painter);
    (*AB).trace (&painter);
}

On redessine ici la figure : on peint le fond en blanc, on trace le repère en rouge puis les points et enfin la droite en bleu.

void Fenetre::mousePressEvent (QMouseEvent *event) {
    int X = event -> x ();
    int Y = event -> y ();
    presse = (*A).select (X, Y) || (*B).select (X, Y);
    if (presse)
        setCursor (Qt::ClosedHandCursor);
}

On teste, dans cet ordre, si la souris est proche de A ou de B. Si c'est le cas l'indicateur de déplacement du point est positionné ainsi que le booléen presse. On change ensuite le curseur.

void Fenetre::mouseMoveEvent (QMouseEvent *event) {
    int X = event -> x ();
    int Y = event -> y ();
    if (presse) {
        (*A).bouge (X, Y);
        (*B).bouge (X, Y);
        (*AB).droite_pt_pt (A, B);
        update ();

Si le déplacement d'un point est en cours (presse = TRUE) alors on modifie ses coordonnées à l'écran (méthode bouge (X, Y);). On recalcule ensuite la droite (AB) puis on redessine la figure (méthode update();). NB la méthode bouge (X, Y); n'agit que sur le point en cours de déplacement.

    } else {
        bool proche = (*A).zone (X, Y) || (*B).zone (X, Y);
        if (proche)
            setCursor (Qt::PointingHandCursor);
        else
            setCursor (Qt::ArrowCursor);
    }
}

Si on bouge la souris sans appuyer sur le bouton en change simplement le curseur à proximité de A ou de B.

void Fenetre::mouseReleaseEvent (QMouseEvent *) {
    (*A).stop();
    (*B).stop();
    presse = false;
    setCursor (Qt::PointingHandCursor);
}

On relâche de bouton de la souris : on remet tous les indicateurs de déplacement à FALSE puis on change le curseur.

NB (*A).zone (X, Y), (*B).stop();... peuvent aussi s'écrire A->zone (X, Y), B->stop();...