Courbe d'une fonction dépendant d'un paramètre

Il s'agit dans cet exemple de tracer la courbe de la fonction f (x) = m x2. C'est un curseur et le "slider" de Qt permettent la récupération de la valeur du paramètre m.

parm_slider.png

Répertoire : fparm_slider. Trois fichiers : main.cpp, appli.h et appli.cpp.

main.cpp

#include <QApplication>

#include "appli.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.

appli.h

#ifndef APPLI_H
#define APPLI_H

#include <QtGui>

#include "geo2D/curseur.h"
#include "geo2D/courbe.h"


class mx2: public fonction {

public:
    double m;
    mx2 (double m);
    double image (double x);
};

La fonction dépendant d'un paramètre est une sur-classe de la classe fonction.

class Dessin: public QWidget {

    Q_OBJECT

public:
    repere *R;
    mx2 *f;
    courbe *c;
    curseur *mcurs;

    bool presse;
    QSlider *slider;

Pointeur sur le curseur de Qt.

Dessin (QWidget *parent = 0);

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

public slots:
    void slider_val (int nval);
};

Méthode invoquée chaque changement de la valeur retournée par le "slider"

class Fenetre: public QWidget {

    Q_OBJECT

public:
    Dessin *canvas;

    Fenetre (QWidget *parent = 0);
};

#endif

 

appli.cpp

/*
 * fparm_slider
 */

#include "appli.h"

bool fonction::def (double) {
    return true;
}

double fonction::image (double) {
    return 0.0;
}

mx2::mx2 (double m) {
    mx2::m = m;
}

double mx2::image (double x) {
    return m * x * x;
}

On construit ici l'ensemble de définition de la fonction carré mx2 et l'expression de l'image de x : m x2.

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

    R = new repere (300, 225, 600, 450, 50.0, 50.0, 1.0, 1.0);
    double m = 1.0;
    mcurs = new curseur (-4.0, 4.0, m, 400, 100, 200, "m", R);
    f = new mx2 (m);
    c = new courbe (f, NULL, R); 
}

Constructeur de la feuille de dessin : on fixe la dimension et les paramètre puis on crée ici les objets géométriques.

void Dessin::paintEvent (QPaintEvent *) {
    setPalette (QPalette (QColor (255, 255, 255)));
    setAutoFillBackground (true);
    QPainter painter (this);
    painter.setPen (Qt::red);
    R -> trace (&painter);
    painter.setPen (Qt::blue);
    c -> trace (&painter);
    mcurs -> trace (&painter);
}

On redessine ici la figure : on peint le fond en blanc, on trace le repère en rouge puis le curseur et la courbe.

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

On teste, dans cet ordre, si la souris est proche du bouton du curseur puis du curseur lui-même.

void Dessin::mouseMoveEvent (QMouseEvent *event) {
    int X = event -> x ();
    int Y = event -> y ();
    if (presse) {
        mcurs -> bouge (X, Y);
        mcurs -> bouge_curseur (X, Y);
        double m = mcurs -> valeur ();
        f -> m = m;
        slider -> setValue ((int) (m * 25.0 + 100));
        update ();

On met à jour le paramètre, le bouton du curseur de Qt puis on relance le tracé..

    } else {
        if (mcurs -> zone (X, Y) || mcurs -> zone_curseur (X, Y))
            setCursor (Qt::PointingHandCursor);
        else
            setCursor (Qt::ArrowCursor);
    }
}

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

void Fenetre::mouseReleaseEvent (QMouseEvent *) {
    mcurs -> stop ();
mcurs -> stop_curseur (); presse = false; setCursor (Qt::PointingHandCursor); }

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

void Dessin::slider_val (int nval) {
    double m = 0.04 * nval - 4.0;
    f -> m = m;
    mcurs -> val = m;
    update ();
}

Si on modifie la position du bouton du curseur de Qt, on met à jour le paramètre m et la position du curseur de la feuille de dessin.

Fenetre::Fenetre (QWidget *parent): QWidget (parent) {
    setGeometry (0, 0, 600, 500);
    canvas = new Dessin (parent);
    canvas -> slider = new QSlider (Qt::Horizontal);
    canvas -> slider -> setRange (0, 200);
    canvas -> slider -> setValue (125);
    connect (canvas -> slider, SIGNAL (valueChanged (int)), canvas, SLOT (slider_val (int)));
    QVBoxLayout *vboite = new QVBoxLayout;
    vboite -> addWidget (canvas -> slider);
    vboite -> addWidget (canvas);
    setLayout (vboite);
}

Constructeur de la fenêtre principale : on crée et on monte verticalement dans cett fenêtre un curseur et la feuille de dessin.