FAQ Qt
FAQ QtConsultez toutes les FAQ
Nombre d'auteurs : 26, nombre de questions : 298, dernière mise à jour : 15 juin 2021
Lorsqu'un widget doit être dessiné ou redessiné, la fonction protégée QPaintEvent est appelée. Pour se dessiner, la majorité des widgets de Qt utilise un QPainter lors de l'appel à cette fonction. Il est donc naturel de suivre cette logique.
L'événement QPaintEvent passé en paramètre indique la zone à redessiner. Cette zone est donnée sous forme de rectangle QPaintEvent::rect ou sous forme quelconque QRegion. Ces informations peuvent être utilisées pour optimiser l'affichage du widget.
La classe QPainter est un outil qui permet de dessiner sur toutes les classes graphiques de Qt : QCustomRasterPaintDevice, QGLFramebufferObject, QGLPixelBuffer, QImage, QPicture, QPixmap, QPrinter, QSvgGenerator, et QWidget.
Cette classe utilise d'autres outils de Qt dont les plus importants sont :
- QPen : définit la manière dont le contour d'une forme est tracé (ligne, point, contour d'une forme...) ;
- QBrush : définit la manière dont l'intérieur d'une forme est peint (intérieur d'un rectangle...).
Voici un exemple.
Certains widgets sont basés sur QAbstractScrollArea, dont le but est de permettre l'affichage d'un widget plus grand que sa zone d'affichage, en ajoutant des barres de défilement, par exemple. Appliquer un painter directement sur celle-ci n'aura pas l'effet souhaité. Cette classe implémente la méthode viewport() qui permet d'accéder au widget qui est réellement affiché. Il faut donc appliquer le painter sur celui-ci.
- prédessin : le dessin en arrière-plan ;
- dessin original : le dessin d'origine ;
- postdessin : le dessin au premier plan.
Les widgets concernés sont QAbstractItemView, QGraphicsView, QMdiArea, QPlainTextEdit, QScrollArea, QTextEdit, QTextBrowser, QColumnView, QHeaderView, QListView, QTableView, QTreeView, QHelpContentWidget, QTreeWidget, QTableWidget, QHelpIndexWidget, QListWidget, QUndoView.
Remarque : comme le traitement avant dessin se dessine en arrière-plan, il peut être totalement effacé par le dessin original ou le postdessin.
L'impression avec Qt est à peu près équivalente au dessin sur un QWidget ou QImage. Il y a plusieurs étapes :
- Créer un QPrinter comme périphérique de dessin ;
- Ouvrir un QPrintDialog pour que l'utilisateur choisisse une imprimante et certaines options ;
- Créer un QPainter pour agir sur le périphérique de dessin ;
- Dessiner une page avec le QPainter ;
- Changer de page avec QPrinter::newPage() ;
- Recommencer les deux étapes précédentes jusqu'à ce que tout soit imprimé.
Sous Windows et macOS, QPrinter utilise les pilotes d'imprimante système. Sous UNIX, il crée un fichier PostScript qu'il envoie à lp ou lpr (vous pouvez définir le programme auquel envoyer le contenu PostScript avec la fonction QPrinter::setPrintProgram()). QPrinter peut aussi être utilisé pour créer un fichier PDF représentant l'impression en appelant setOutputFormat(QPrinter::pdfFormat).
void
printImage (const
QImage
&
image)
{
QPrintDialog
printDialog (&
printer, this
)
if
(printDialog.exec())
{
QPainter
painter (&
printer);
QRect
rect =
painter.viewport ()
QSize
size =
image.size ();
size.scale (rect.size (), Qt
::
KeepAspectRatio);
painter.setViewport (rect.x (), rect.y (), size.width (), size.height ());
painter.setWindow (image.rect ());
painter.drawImage (0
, 0
, image);
}
}
Écrire du texte verticalement peut être effectué de plusieurs façons. La méthode la plus simple est de créer un QTextDocument dans la fonction paintEvent() et d'utiliser setHtml() pour définir le texte contenant des tags "</br>" pour les sauts de lignes.
Une autre méthode pourrait être de parcourir tous les QChar de la QString et de les positionner verticalement dans la fonction paintEvent(). Pour cela, vous devez calculer la hauteur entre chaque élément.
Si vous voulez tourner les caractères, vous pouvez tout simplement tourner le QPainter de 90°.
Finalement, si vous devez dessiner le texte vous-même, alors le plus simple serait d'utiliser QLabel pour afficher le texte verticalement. Il suffit d'ajouter un "\n" après chaque caractère.
L'exemple suivant présente quelques possibilités.
Voici comment appliquer une rotation avec QPainter sur une image dessinée dans un widget personnalisé. On crée une classe qui dérive de QWidget et on redéfinit la méthode paintEvent(). On manipule ensuite le QPainter associé au widget en lui appliquant des transformations.
Il faut savoir qu'avec Qt, les transformations s'appliquent à l'origine du repère (contrairement à d'autres frameworks où elles s'appliquent par exemple à l'objet dessiné). Ainsi, effectuer une translation de (x,y) puis une rotation d'angle alpha équivaut à déplacer le centre du repère selon un vecteur (x,y), et de pivoter ses axes d'un angle alpha. Pour rappel, le repère associé au painter d'un QWidget est par défaut centré aux coordonnées (0,0) de ce widget (le coin supérieur gauche).
Il est conseillé de stocker la pixmap en variable membre de classe afin de ne pas avoir à la recharger à chaque paintEvent() et ainsi alléger le rafraîchissement de l'application. Il est possible de redimensionner la pixmap avec la méthode QPixmap::scaled() (à faire de préférence dans le constructeur).