GeckoGeek.fr

Paradigme d'un lézard

Jeudi 19 Octobre 2017

Dessiner dans un QPainter des formes et images en C++

Par Vinz le 21/07/2009 dans Programmation | 2 commentaires

Ayant commencé dernièrement à programmer un peu avec QT (librairie C++) je me suis aperçu que le manque d’exemples concrets était assez énorme. La documentation des classes est vraiment parfaite (cf ici doc pour la 4.5), mais pour le reste on se retrouve vite coincé entre les exemples complexes officiels, les topics de forums et quelques sites (type la communauté fr de QT). J’essayerai donc de poster quelques exemples de choses simples ou plus complexes (on va commencer par le simple =]).

Introduction

Dans ce billet nous allons voir comment dessiner dans un QLabel diverses formes (et aussi des images). Nous allons pour cela dériver la classe QLabel (chose assez commune dans QT). Notons que ce QLabel devra par la suite être intégré dans un layout. Mais pourquoi dériver QLabel ? Tout simplement parce que si vous souhaitez récupérer certains évènements (comme les actions de la souris) de manière précise, alors c’est préférable (voire obligatoire pour une bonne précision). Pour commencer veuillez créer deux nouveaux fichiers (correspondant au .h et .cpp). Nous allons appeler notre classe ZoneDessin, donc si vous êtes en manque d’inspiration appelez les ZoneDessin.h / .cpp :-)

Here we go, commençons par le header file (ZoneDessin.h). Nous allons nous contenter de redéfinir le paintEvent pour ce billet (je vous laisse ajouter les bons includes en haut du fichier).

class ZoneDessin : public QLabel {

	Q_OBJECT

	public:
		ZoneDessin(QWidget *parent);
		~ZoneDessin();

	private:
		void paintEvent(QPaintEvent *);

};

Avant de commencer je vous recommande de définir le fond de votre QLabel comme blanc (afin d’éviter de dessiner sur du noir). Pour ceci veuillez placer cette ligne (qui est un bout de feuille de style) dans le constructeur de votre classe :

setStyleSheet("background-color:rgb(255, 255, 255); margin:0;padding:0;margin:0");

Dessiner une forme

Voici une architecture vide du paintEvent à mettre dans vos fichier source (ZoneDessin.cpp). Dedans nous rajoutons un QPainter qui va nous permettre de dessiner des formes à chaque fois que paintEvent() est appelé (soit lors d’un update()).

void ZoneDessin::paintEvent(QPaintEvent *) { 

	QPainter painter(this);

		// mes dessins

	painter.end();

}

Les formes disponibles sont assez nombreuses (cf la documentation sur QPainter) : points, lignes, arcs de cercle, cercles, polygones, … Pour chaque forme vous avez plusieurs possibilités pour créer l’objet. Vous pouvez par exemple utiliser des QPoint (objet QT comportant une coordonnée x et y) ou bien directement définir la position x et y (etc). Vous utiliserez la méthode qui vous sera la plus simple en fonction de l’architecture de votre programme.

Voici un petit exemple où l’on trace un polygone. Pour l’exemple on va rajouter des points avec putPoints() qui prend en entrée : début d’insertion des points, nombre de points, xPoint1, yPoint1, xPoint2, yPoint2, …

void ZoneDessin::paintEvent(QPaintEvent *) { 

	QPainter painter(this);

	// Définition de la variable
	QPolygon myPolygon;
	// Rajout de 1 point
	myPolygon.putPoints(0, 1, 100, 200);
	// Rajout de 2 points
	myPolygon.putPoints(1, 2, 200, 250, 250, 350);
	// Rajout de 1 point
	myPolygon.putPoints(3, 1, 100, 400);

	// On dessine le polygone définit plus haut
	painter.drawPolygon(myPolygon);

	painter.end();

}

Le polygone dessiné est alors assez basique. Si vous souhaitez y rajouter un peu de couleur alors il vous suffit d’indiquer une couleur à votre “pinceau” et d’indiquer que le polygone doit être remplie (“Qt::WindingFill“) ! Et pour que cela soit un peu plus stylisé nous laisserons le fond un peu opaque (dernier paramètre de “QColor“). Le code devient alors ceci :

void ZoneDessin::paintEvent(QPaintEvent *) { 

	QPainter painter(this);

	// Définit de la couleur de fond
	painter.setBrush(QColor(255, 0, 0, 100));

	// Définition de la variable
	QPolygon myPolygon;
	// Rajout de 1 point
	myPolygon.putPoints(0, 1, 100, 200);
	// Rajout de 2 points
	myPolygon.putPoints(1, 2, 200, 250, 250, 350);
	// Rajout de 1 point
	myPolygon.putPoints(3, 1, 100, 400);

	// On dessine le polygone définit plus haut
	painter.drawPolygon(myPolygon, Qt::WindingFill);

	painter.end();

}

Voici le résultat : à gauche le polygone sans couleur ni remplissage (et sur fond blanc), et à droite le même polygone avec remplissage rouge et opacité.

Ajouter une image

Et si l’on souhaite dessiner une image c’est assez simple. Il suffit juste de connaître la bonne ligne pour convertir l’image (en général une QImage) et l’afficher. Le premier paramètre correspond à la position, mais il est possible de passer par deux entiers (int positionX, int positionY) au lieu de passer par un QPoint(int x, int y).

void ZoneDessin::paintEvent(QPaintEvent *) { 

	QPainter painter(this);

	painter.drawImage(QPoint(100, 100), QImage("chemin-vers-image.ext"));

	painter.end();

}

Aller plus loin ?

Nous avons abordé quelques bases pour dessiner avec un QPainter (ici dans un QLabel). Il existe beaucoup de possibilités de customisation, c’est pourquoi je recommande fortement de visiter la documentation officielle qui répertorie toutes les fonctions.
La prochaine étape serait de dessiner ces formes directement avec la souris. Je n’ai pas encore le temps de faire ce billet (plus tard surement). Mais grossièrement pour les intéréssés il “suffit” de rajouter une liste d’objets (par exemple une liste de QPoint(s) et utiliser un QVector pour faire la liste), et de dessiner cette liste à chaque refresh. Pour récupérer les actions de la souris, redéfinissez les mouseEvent (mousePressEvent, mouseReleaseEvent, mouseMoveEvent). Ou bien vous pouvez aussi attendre un peu que j’ai le temps d’écrire un petit tutorial à ce sujet :-)

Commentaires (2)
  1. jojo le 31 Jan 2010 à 04:25

    Good job, en effet bien pratique pour s’y retrouver.

  2. lookency le 29 Nov 2013 à 12:07

    Merci pour ton tuto, et vivement je souhaite que tu aies le temps d’écrire un autre tuto concernant les dessins directement avec la souris(selon les clicks de l’user) comme tu l’as signifié dans la partie “Allez plus loin?” et aussi comme tu l’as dit en debut il n’y a vraiment pas d’exmples pouvant nous faire assimiler facilement les choses. Personnelement je suis beaucoup interessé par la dernière partie(“Aller plus loin?”)car j’envisage de developper de “petites” applications 2D(pour l’instant), encore une fois merci.
    NB: Si possible j’aimerais qu’on puisse travailler ensemble afin d’ameliorer mes connaissances. Bonne journée.


Laisser un commentaire