Vous êtes sur la page 1sur 22

1 Composants personnalisés

1.1 Créer ses propres composants


– Pour créer son propre composant on peut

– créer un composant héritant d’un autre composant et le personnalisant

– la personnalisation ne doit pas entraver le comportement par dé-


faut du composant personnalisé

– créer son propre composant en écrivant une classe qui hérite de QWidget ;
il faut alors soi-même :

– gérer l’événementiel de bas niveau (souris, clavier)


– créer l’événementiel de haut niveau (événements, signaux)
– gérer l’affichage du composant

1. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


1.2 Personnalisation avec les signaux
– Pour qu’un un composant personnalisé puisse émette des signaux :

– déclarer des méthodes signaux dans signals:

– Pour faire émettre un signal au composant :

– connecter le signal directement à un signal d’un sous-composant (pour


en cacher l’origine précise)
– émettre au bon moment le signal et sa valeur : emit signal(valeur)
– ne pas entraver les signaux du composant personnalisé

– Exemple : bouton comptant le nombre de fois où il a été cliqué et émet un


signal quand cela dépasse une limite

2. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


class boutonCompteur : public QPushButton {
Q_OBJECT
public:
boutonCompteur(int valeurLimite=10, QWidget *parent = nullptr);
int valeur() const;
void changeValeur(int v);
signals:
void clicked(int nbClics); //bouton cliqué
void limiteDepassee(); //limite dépassée
private:
int d_nbClics;
int d_valeurLimite;
void afficheNbClics();
private slots:
void onClic(); //quand bouton cliqué
};

3. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


boutonCompteur::boutonCompteur(int valeurLimite, QWidget *parent):
QPushButton{parent}, d_nbClics{0}, d_valeurLimite{valeurLimite}
{
afficheNbClics();
connect(this,&QPushButton::clicked, this,&boutonCompteur::onClic);
}

void boutonCompteur::afficheNbClics() {
setText(QString::number(d_nbClics));
}

void boutonCompteur::onClic() {
++d_nbClics;
afficheNbClics();
emit clicked(d_nbClics);
if (d_nbClics>d_valeurLimite)
{
emit limiteDepassee();
}
}

4. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– S’utilise comme un contrôle normal

private slots:
void onClique(int nbClics);
void onDepasse();

auto compteur = new boutonCompteur{5};


...
connect(compteur, &boutonCompteur::clicked,
this, &MainWindow::onClique);
connect(compteur, &boutonCompteur::limiteDepassee,
this, &MainWindow::onDepasse);

void MainWindow::onClique(int nbClics)


{
nb_clics = nbClics;
vue_afficheClics(nb_clics);
}

5. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


1.3 Gestion des événements de bas niveau (souris et clavier)
– Quand l’utilisateur interagit avec un composant c de l’application :

– Qt crée un événement e : un objet de type dérivé de QEvent (p.ex.


QResizeEvent, QPaintEvent, QMouseEvent, QKeyEvent, . . . )
– il donne l’événement à traiter au composant en appelant sa méthode
event : c->event(e)
– cette méthode étudie le type de l’événement et le distribue à la bonne
méthode du composant pour le traiter
(p.ex. c->paintEvent(e) si e est un QPaintEvent)

6. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


1.3.1 Personnaliser l’événementiel avec des événements
– Redéfinir la méthode qui traite l’événement :
p.ex. monComposant::mouseMoveEvent(QMouseEvent *e)
– Faire les traitements locaux
– S’il y a besoin de laisser faire le traitement par défaut : appeler la méthode
de la classe de base
p.ex. QWidget::mouseMoveEvent(e)

7. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


1.3.2 Souris
– Les événements générés par la souris concernent les boutons (pressés ou
relâchés) et le mouvement
– Ils sont de type QMouseEvent
– Cet événement permet de connaître :

– les coordonnées de la souris (par rapport au composant) : x(), y(),


pos()
– le bouton concerné : button()
(renvoie Qt:: No/Left/Middle/Right Button)
– les touches appuyées en même temps : modifiers()
(renvoie Qt:: No/Shift/Control/Alt Modifier )

8. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– Pour traiter un événement souris, redéfinir les méthodes suivantes qui sont
appelées quand le composant reçoit un événement :

– mousePressEvent(QMouseEvent *e) : un bouton de souris est


pressé
– mouseReleaseEvent(QMouseEvent *e) : un bouton de souris est
relâché
– mouseDoubleClickEvent(QMouseEvent *e) : un bouton de sou-
ris est double-cliqué (les événements pour souris pressée et relâchée
seront aussi reçus)
– mouseMoveEvent(QMouseEvent *e) : la souris est déplacée

– Qt signale aussi avec un QEvent :

– enterEvent(QEvent *e) : la souris entre dans le composant


– leaveEvent(QEvent *e) : la souris quitte le contrôle

9. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


Contrôle qui indique quand la souris est pressée et relâchée et où

class widgetSouris : public QWidget {


Q_OBJECT
public:
explicit widgetSouris(QWidget *parent = nullptr);
signals:
void sourisPressee(const QPoint& pos);
void sourisRelachee(const QPoint& pos);
private:
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
};

10. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


void widgetSouris::mousePressEvent(QMouseEvent *e) {
emit sourisPressee(e->pos());
}

void widgetSouris::mouseReleaseEvent(QMouseEvent *e) {


emit sourisRelachee(e->pos());
}

1.3.3 Clavier
– Les événements générés par le clavier concernent les touches (pressées ou
relâchées) et les caractères tapés
– Ils sont de type QKeyEvent

11. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– Cet événement permet de connaître :

– le code de la touche : key() (renvoie Qt::Key_Nomtouche)


– le texte (chaîne) correspondant à la touche : text()
– les touches appuyées en même temps : modifiers()
(renvoie Qt:: No/Shift/Control/Alt Modifier )

Pour traiter un événement clavier, redéfinir les méthodes suivantes qui sont
appelées quand le composant reçoit un événement :

– keyPressEvent(QKeyEvent *event) : une touche est pressée


– keyReleaseEvent(QKeyEvent *event) : une touche est relâchée
– dans les deux cas : si on ne modifie pas la touche, appeler ensuite
classeDeBase::keyPress/ReleaseEvent(event) pour que le
traitement par défaut ait lieu

12. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


2 Dessin
2.1 Peintre
– On ne dessine pas directement dans une fenêtre, sur un composant, mais
sur un objet peignable en utilisant un peintre
– Un objet peignable est un objet dans lequel on peut dessiner : composant,
image, . . .
– Un peintre représente :

– le support sur lequel le dessin est fait


– les outils, pinceau, brosse, . . . avec lesquels le dessin est fait

– On crée un peintre sur un objet peignable avec QPainter :


QPainter paint{objetPeignable}
– On utilise ensuite les différentes méthodes sur paint pour dessiner dans
l’objet peignable.

13. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


2.2 Outils
– Toutes les valeurs données dans la suite sont préfixées par Qt::
– Couleur : QColor

– QColor(red,green,blue)
– QColor(nom) : white/black/reg/green/blue
– méthodes red/green/blue(), setRGB(red,green,blue)

– Brosse : QBrush, remplissage (couleur, style)

– QBrush(couleur,style)
– styles : NoBrush, SolidPattern, HorPattern, VerPattern, CrossPatter
– style : style(), setStyle(style)
– couleur : color(), setColor(couleur)

14. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– Pinceau : QPen, style du tracé (couleur, largeur, style)

– QPen(couleur), QPen(style tracé)


– couleur : color()/setColor(couleur)
– style tracé : style()/setStyle(style)
style : NoPen, SolidLine, DashLine, DotLine, DashDotLine
– style extrémités : capStyle()/setCapStyle(style)
style : SquareCap, FlatCap, RoundCap
– style jointures : joinStyle()/setJoinStyle(style)
style : MiterJoin, BevelJoin, RoundJoin
– largeur : width()/setWidth(largeur) : indiquer largeur=0 pour
avoir toujours 1 pixel

– Fonte : QFont, affichage du texte

– QFont(famille, taillePoint, poids, italic = false)

15. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


2.3 Dessiner avec un peintre
– Styles des dessin :

– setBrush(brosse) : brosse du pinceau


– setBackground(brosse) : brosse pour effacer
– setFont(fonte) : fonte pour l’affichage du texte
– setPen(pinceau)/setPen(couleur) : pinceau de tracé

– Transformations des coordonnées :

– translate(qreal dx, qreal dy)


– scale(qreal sx, qreal sy)
– rotate(qreal angle)

16. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– Tracés (rectangle = un QRect ou les coordonnées xtopleft, ytopleft,
width, height du rectangle) :

– drawEllipse(rectangle) : trace l’ellipse délimitée par le rectangle


– drawArc/drawChord/drawPie(rectangle,startAngle,spanAngle)
(angles en 1/16e de degrés) : trace l’arc de l’ellipse délimitée par le rec-
tangle
– drawPoint(x,y) : affiche point
– drawLine(x1,y1,x2,y2 ou p1,p2) : trace segment de droite
– drawRect(rectangle) : trace le rectangle
– fillRect(rectangle,couleur ou brosse) : remplit le rectangle
– eraseRect() : efface avec brosse du fond
– drawPolygon(polygone) : trace le polygone
– drawText(x,y,texte)

17. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


2.4 Dessiner dans un composant
– On dessine dans un composant quand Qt envoie un événement QPaintEvent
au composant :

– pour faire une mise à jour de l’affichage quand le composant graphique


doit se ré-afficher après avoir été caché ou parce qu’on a changé sa
taille
– quand quelqu’un demande au composant de mettre à jour son affi-
chage en appelant sa méthode update()

– Dans tous les cas, l’événement est traité par la méthode


paintEvent(QPaintEvent *e) du composant
– La méthode crée le peintre sur le composant et dessine avec :

void monComposant::paintEvent(QPaintEvent*) {
QPainter paint{this};
//dessiner avec paint
}

18. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


– Le dessin peut être réparti dans des méthodes :

– qui prennent un peintre en paramètre


– appelées dans paintEvent()

– Contrôle qui stocke des points rentrés à la souris (ajoutés avec le bouton
gauche, enlevés avec le bouton droit)

19. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


class widgetPolygon : public QWidget {
Q_OBJECT
public:
explicit widgetPolygon(QWidget *parent = 0);
QSize sizeHint() const; //taille préférée par défaut
private:
QPolygon d_pol;
void paintEvent(QPaintEvent* );
void mouseReleaseEvent(QMouseEvent* e);
void ajouteSommet(const QPoint& pt);
void enleveSommet(const QPoint& pt);
void dessinePolygone(QPainter& paint, const QPolygon& pol);
void dessineSommet(QPainter& paint, const QPoint& p);
};

20. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


void widgetPolygon::paintEvent(QPaintEvent* ) {
QPainter paint{this};
tracePolygone(paint, d_pol);
dessineSommets(paint, d_pol);
}

void widgetPolygon::tracePolygone(QPainter& paint, const QPolygon& pol) {


for (int i=1; i<pol.size(); ++i) {
paint.drawLine(d_pol[i-1], d_pol[i]);
}
if (!pol.empty()) paint.drawLine(d_pol[0], d_pol.back());
}

void widgetPolygon::dessineSommets(QPainter& paint, const QPolygon& pol) {


for (const auto& p : pol) { dessineSommet(paint,p); }
}

void widgetPolygon::dessineSommet(QPainter& paint, const QPoint& p) {


paint.drawEllipse(p.x()-3, p.y()-3, 6, 6);
}

21. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière


void widgetPolygon::mouseReleaseEvent(QMouseEvent* e)
{
if (e->button() == Qt::LeftButton)
{
ajouteSommet(e->pos());
}
else if (e->button() == Qt::RightButton)
{
enleveSommet(e->pos());
}
update();
}

void widgetPolygon::ajouteSommet(const QPoint& pt)


{
d_pol.push_back(pt);
}

22. Prog événementielle et interfaces graphiques – L2 INFO Stéphane Rivière

Vous aimerez peut-être aussi