Retrouvez cet article dans : Linux Magazine 84
Nous avons vu, le mois dernier, comment créer et parcourir des documents structurés.
Examinons maintenant les possibilités offertes pour mettre tout cela en forme, aussi bien les caractères que les blocs ou les tableaux.
Les mises en forme pouvant être appliquées à une portion de texte sont représentées par quelques classes dérivant toutes de la classe
QTextFormat.
Son interface est fondée sur un mécanisme de propriétés : en exagérant un peu, on pourrait considérer que cette classe n’est finalement qu’un dictionnaire associant des valeurs à des identifiants numériques entiers, agrémenté de quelques fioritures.
Les identifiants des propriétés sont issus de l’énumération
QTextFormat::Property. Reportez-vous à la documentation pour en avoir la liste, sachant que les explications sont un peu, disons, succinctes.
Vous pouvez également définir vos propres propriétés, dont les identifiants doivent être supérieurs à
QTextFormat::UserProperty.
Les valeurs associées sont représentées par des instances de
QVariant, le type " multimorphe " de Qt, que l’on pourrait comparer au type
boost::any [1] du composant Any de l’ensemble de bibliothèques Boost.
En poursuivant dans l’exagération, les méthodes de
QTextFormat peuvent donc se résumer aux trois suivantes :
QVariant property(int) const pour obtenir la valeur associée à un identifiant donné ;
void setProperty(int, QVariant) pour attribuer une valeur à un identifiant ;
QMap<int, QVariant> properties() const qui retourne l’ensemble des couples (identifiant, valeur) stockés sous la forme d’un dictionnaire.
Toutefois, des méthodes spécialisées existent pour les utilisations les plus courantes, les classes dérivées de
QTextFormat ne faisant finalement guère plus qu’enrichir ces facilités.
Au niveau de la classe de base, citons simplement :
background() et setBackground() pour obtenir et fixer l’arrière-plan de l’élément de texte, par exemple la couleur de fond d’un paragraphe ;
foreground() et setForeground() pour obtenir et fixer l’avant-plan, par exemple la couleur des caractères d’un mot.
Notez qu’arrière- et avant-plan sont définis par des instances de
QBrush : cela permet d’utiliser des motifs plus ou moins complexes, sans se limiter à une simple couleur. Voyons cela tout de suite à partir d’un exemple.
Mise en forme des caractères
Une mise en forme est normalement appliquée en passant par un curseur, de type
QTextCursor, tout comme vous le feriez sans même y penser dans un traitement de textes.
Pour ce qui est des caractères, utilisez la classe
QTextCharFormat (dérivée de
QTextFormat). Réalisons un premier exemple :

Le premier mot est en italique, le deuxième est en gras avec un fond dégradé, le troisième est petit, souligné et surligné, enfin, les caractères du dernier sont de grande taille et dessinés avec un remplissage et une bordure pointillée en dégradé.
Voici le code utilisé pour cet exemple :
1 #include <QTextEdit>
2 #include <QTextCharFormat>
3 #include <QTextCursor>
4 #include <QLinearGradient>
5 #include <QApplication>
6 int main(int argc, char* argv[])
7 {
8 QApplication app(argc, argv) ;
9 QTextEdit te(0) ;
10 QFont fnt = te.font() ;
11 fnt.setPointSize(24) ;
12 QTextDocument* doc = te.document() ;
13 doc->setDefaultFont(fnt) ;
14 QTextCursor curseur(doc) ;
15 curseur.insertText(“Un tout petit exemple”) ;
Pour commencer, on crée simplement une instance de
QTextEdit pour afficher notre document, dans lequel est insérée une chaîne de caractères. Rien de bien nouveau par rapport au mois dernier. Le petit jeu sur la police de caractères (lignes 10, 11 et 13) permet de définir les caractères utilisés par défaut dans le document : ici, ils sont agrandis pour les besoins de cet article.
16 // Création des motifs
17 QLinearGradient grad_rj(0.0, 0.0, 0.0, 8.0) ;
18 grad_rj.setColorAt(0.0, Qt::red) ;
19 grad_rj.setColorAt(0.9, Qt::yellow) ;
20 grad_rj.setSpread(QGradient::ReflectSpread) ;
21 QBrush brush_rj(grad_rj) ;
22 QLinearGradient grad_bc(0.0, 0.0, 8.0, 8.0) ;
23 grad_bc.setColorAt(0.0, Qt::blue) ;
24 grad_bc.setColorAt(0.9, Qt::cyan) ;
25 grad_bc.setSpread(QGradient::ReflectSpread) ;
26 QPen pen_out(QBrush(grad_bc), 2.0, Qt::DashLine) ;
Ensuite sont créés les motifs (dégradés) que nous allons utiliser.
brush_rj est une brosse (
QBrush) pour le remplissage, tandis que
pen_out est un pinceau (
QPen) pour le dessin de courbes. Remarquez que le pinceau utilise lui-même une brosse...
27 // Création des styles
28 QTextCharFormat petit_fmt ;
29 petit_fmt.setFontPointSize(12.0) ;
30 QTextCharFormat grand_fmt ;
31 grand_fmt.setFontPointSize(52.0) ;
32 grand_fmt.setTextOutline(pen_out) ;
33 QTextCharFormat fond_grad_fmt ;
34 fond_grad_fmt.setBackground(brush_rj) ;
35 QTextCharFormat forme_grad_fmt ;
36 forme_grad_fmt.setForeground(brush_rj) ;
37 QTextCharFormat italique_fmt ;
38 italique_fmt.setFontItalic(true) ;
39 QTextCharFormat gras_fmt ;
40 gras_fmt.setFontWeight(QFont::Bold) ;
41 QTextCharFormat sursous_fmt ;
42 sursous_fmt.setFontUnderline(true) ;
43 sursous_fmt.setFontOverline(true) ;
Puis, nous créons les styles de caractères voulus, sous la forme d’instances de
QTextCharFormat. Remarquez que les tailles de caractères sont données par des réels (lignes 29 et 31), de type
qreal, équivalent au type
double.
L’idée est de définir une taille (relativement) indépendante du périphérique utilisé, ce qui offre une grande précision lorsque le dessin est effectué sur une imprimante (ou un fichier PDF ou PostScript) plutôt qu’à l’écran.
Enfin, les styles sont appliqués aux mots de la chaîne en les sélectionnant l’un après l’autre par le curseur :
44 // Application des styles
45 curseur.movePosition(QTextCursor::Start) ;
46 curseur.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor) ;
47 curseur.setCharFormat(italique_fmt) ;
48 curseur.movePosition(QTextCursor::NextWord) ;
49 curseur.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor) ;
50 curseur.setCharFormat(gras_fmt) ;
51 curseur.mergeCharFormat(fond_grad_fmt) ;
52 curseur.movePosition(QTextCursor::NextWord) ;
53 curseur.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor) ;
54 curseur.mergeCharFormat(petit_fmt) ;
55 curseur.mergeCharFormat(sursous_fmt) ;
56 curseur.movePosition(QTextCursor::NextWord) ;
57 curseur.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor) ;
58 curseur.mergeCharFormat(forme_grad_fmt) ;
59 curseur.mergeCharFormat(grand_fmt) ;
60 te.show() ;
61 return app.exec() ;
62 }
Les lignes 45 à 47 sélectionnent le premier mot, puis appliquent la mise en forme de caractère définie par
italique_fmt au moyen de la méthode
setCharFormat() de
QTextCursor. L’effet est de remplacer la mise en forme existante de la sélection du curseur par celle passée en paramètre. Voyons le mot suivant (sélectionné par les lignes 48 et 49), auquel nous donnons un fond dégradé et une mise en gras. Le gras est défini par la ligne 50.
Le fond est ajouté par la ligne 51, par la méthode
mergeCharFormat(). L’effet est ici de remplacer les propriétés de la sélection seulement par celles effectivement définies dans le format donné en paramètre. On réalise ainsi une fusion de deux formats, les propriétés de celui donné en paramètre ayant la précédence sur ceux existant en cas de conflit. D’une manière générale, il est préférable de n’utiliser que
mergeCharFormat() afin d’obtenir une combinaison cohérente entre une mise en forme existante et une nouvelle. Les situations où il est nécessaire de remplacer complètement l’aspect des caractères sont, en pratique, moins fréquentes. C’est ce qui est fait pour les deux derniers mots (lignes 54-55 et 58-59).
Mise en forme des blocs
Voyons maintenant la mise en forme de blocs, c’est-à-dire de paragraphes. La classe dérivée de
QTextFormat à utiliser est cette fois
QTextBlockFormat. Nous allons produire le document suivant :

Le premier paragraphe est aligné à gauche, la première ligne indentée. Le deuxième est centré. Le troisième est justifié, avec une marge à gauche et à droite.
Voici le code :
1 #include <QTextEdit>
2 #include <QTextCharFormat>
3 #include <QTextBlockFormat>
4 #include <QTextCursor>
5 #include <QApplication>
6 int main(int argc, char* argv[])
7 {
8 QString texte(“Ceci est du texte “) ;
9 texte = texte + texte ;
10 texte = texte + texte ;
11 QApplication app(argc, argv) ;
12 QTextEdit te(0) ;
13 QFont fnt = te.font() ;
14 fnt.setPointSize(16) ;
15 QTextDocument* doc = te.document() ;
16 doc->setDefaultFont(fnt) ;
17 QTextCursor curseur(doc) ;
18 // Définition des styles
19 QTextBlockFormat gauche ;
20 gauche.setTextIndent(32) ;
21 gauche.setBackground(QColor(Qt::red).light()) ;
Le début ne présente rien d’exceptionnel. Un premier style de paragraphe est créé ligne 19, pour lequel on demande une indentation de la première ligne de 32 pixels. L’arrière-plan sera rouge, défini par la méthode
setBackground() héritée de
QTextFormat. L’alignement par défaut étant à gauche, ce sera également celui de notre paragraphe.
22 QTextBlockFormat centrer ;
23 centrer.setBackground(Qt::green) ;
24 centrer.setAlignment(Qt::AlignHCenter) ;
Deuxième style, pour le deuxième paragraphe. Cette fois, on demande un alignement centré.
25 QTextBlockFormat justifier ;
26 justifier.setBackground(Qt::yellow) ;
27 justifier.setForeground(Qt::blue) ;
28 justifier.setAlignment(Qt::AlignJustify) ;
29 justifier.setLeftMargin(24.0) ;
30 justifier.setRightMargin(32.0) ;
31 justifier.setTopMargin(16.0) ;
32 justifier.setBottomMargin(24.0) ;
Troisième et dernier style, pour un paragraphe justifié. Les méthodes
set*Margin() permettent de spécifier des marges en pixels pour chacun des quatre bords du paragraphe. Remarquez que l’on demande un avant-plan bleu (ligne 27), ce qui sera sans aucun effet : il s’agit d’une mise en forme de caractères, sans objet pour un bloc. La ligne 27 est donc parfaitement inutile.
33 QTextCharFormat italique ;
34 italique.setFontItalic(true) ;
35 // Insertion des blocs de texte
36 curseur.insertText(texte) ;
37 curseur.setBlockFormat(gauche) ;
Enfin nous insérons le texte. La méthode
setBlockFormat() de
QTextCursor (ligne 37) agit soit sur le bloc contenant le curseur en l’absence de sélection, soit sur tous les blocs " touchés " par une sélection. Elle est similaire à la méthode
setCharFormat() vue dans la section précédente, une méthode
mergeBlockFormat() étant également disponible pour fusionner deux mises en forme de paragraphe.
38 curseur.insertBlock(centrer) ;
39 curseur.insertText(texte) ;
40 curseur.insertBlock(justifier, italique) ;
41 curseur.insertText(texte) ;
42 te.show() ;
43 return app.exec() ;
44 }
Un nouveau bloc est inséré par
insertBlock(). Une première version existe sans paramètre. Celle utilisée ligne 38 permet de spécifier la mise en forme du nouveau bloc. Ligne 40, non seulement on donne la mise en forme du bloc, mais également la mise en forme par défaut des caractères dans ce bloc. Il est également possible de changer le style des caractères d’un bloc entier, en passant une instance de
QTextCharFormat à
setBlockCharFormat() (pour remplacer le style existant) ou
mergeBlockCharFormat() (pour fusionner deux styles). Il ne s’agit bien que d’une mise en forme par défaut, rien n’empêche par la suite d’appliquer un autre style indépendamment à chacun des caractères.
Les listes
Un document peut contenir des listes, dont les items sont agrémentés de puces (cercles, disques pleins ou carrés) ou d’une numérotation (nombres, lettres minuscules ou majuscules). Ces listes peuvent être imbriquées les unes dans les autres, mais leur manipulation par programmation demande un peu de " bricolage ". Voyons comment réaliser le document suivant :

Les listes sont représentées par des instances de la classe
QTextList, elle-même dérivant de la classe
QTextBlockGroup, qui représente un groupe de paragraphes (blocs). Le début du programme nous est maintenant familier :
1 #include <QTextEdit>
2 #include <QTextList>
3 #include <QTextListFormat>
4 #include <QTextBlockFormat>
5 #include <QTextCursor>
6 #include <QApplication>
7 int main(int argc, char* argv[])
8 {
9 QApplication app(argc, argv) ;
10 QTextEdit te(0) ;
11 QFont fnt = te.font() ;
12 fnt.setPointSize(16) ;
13 QTextDocument* doc = te.document() ;
14 doc->setDefaultFont(fnt) ;
15 QTextCursor curseur(doc) ;
16 curseur.insertText(“Un peu de texte...”) ;
17 curseur.insertBlock() ;
18 QTextBlockFormat bf ;
La raison de l’insertion d’un bloc ligne 17 va apparaître immédiatement. Une première façon de créer une liste est de passer par la méthode
insertList() de
QTextCursor, qui attend une instance de
QTextListFormat en paramètre pour spécifier l’aspect de la nouvelle liste – notamment, le style de décoration et l’indentation.
insertList() insère une nouvelle liste à l’endroit où se trouve le curseur, en insérant un nouveau bloc puis en positionnant le curseur au début de celui-ci.
Le problème est alors que le curseur se trouve " dans " une liste, d’où il est assez difficile de le faire sortir en pratique. Aussi est-il préférable d’appliquer le schéma suivant :
19 // première liste
20 bf.setBackground(Qt::green) ;
21 QTextListFormat liste_fmt ;
22 liste_fmt.setStyle(QTextListFormat::ListLowerAlpha) ;
23 curseur.movePosition(QTextCursor::Left) ;
24 QTextList* liste_1 = curseur.insertList(liste_fmt) ;
25 curseur.mergeBlockFormat(bf) ;
26 curseur.insertText(„Liste 1, premier item\n“) ;
27 curseur.insertText(QString::fromUtf8(„Liste 1, deuxième item\n")) ;
La liste est insérée ligne 24. Juste avant, le curseur est déplacé d’un cran vers la gauche. Comme ce déplacement vient juste après l’insertion d’un bloc (ligne 17), notre curseur se trouve donc à la fin d’un bloc (qui contient ici Un peu de texte), suivi par un bloc vide. Ce bloc vide va être déplacé par l’insertion de la liste : celle-ci sera donc suivie d’un bloc " normal ", ce qui nous permettra de sortir de la liste aisément.
Mais peut-être êtes-vous étonné de la présence de l’invocation de
mergeBlockFormat() ligne 25, dont l’objet est de donner un fond vert (voir la ligne 20) à notre liste.
QTextListFormat dérivant de
QTextFormat, elle dispose également de la méthode
setBackground(). Malheureusement ce genre de propriétés est complètement ignoré par
insertList() : définir une couleur de fond dans la variable
liste_fmt (ligne 21) est donc sans effet. S’agit-il d’un bogue ou d’une volonté délibérée, la question reste ouverte. Pour contourner le problème, on définit simplement une mise en forme de bloc (lignes 18 et 20) que l’on fusionne avec le premier bloc de la liste nouvellement insérée (ligne 25), c’est-à-dire son premier élément. Les éléments insérés par la suite conserveront cette mise en forme.
Poursuivons. La ligne 26 a pour effet d’insérer le texte du premier item de la liste, et de créer un deuxième item. Les items sont créés simplement en insérant des blocs, par exemple avec la méthode
insertBlock() de
QTextCursor.
Or, la présence d’un caractère de fin de ligne (
‘\n’) dans une chaîne de caractères provoque justement l’insertion d’un bloc : le caractère
‘\n’ qui termine les chaînes données lignes 26 et 27 provoque donc l’insertion d’item. Remarquez sur la capture d’écran que le dernier élément de cette première liste est vide : il a été logiquement inséré par le
‘\n’ final ligne 27, mais aucun texte n’a, par la suite, été inséré dedans.
Conséquence importante de ce principe d’ajout des éléments à une liste : un item dans une liste est représenté par un bloc et un seul. Il n’est donc pas possible d’avoir des éléments de liste composés de plusieurs blocs. Enfin, si vous vous demandez la raison de la présence de la méthode statique
fromUtf8() de la classe
QString ligne 27, elle est nécessaire pour que la conversion en Unicode de la chaîne se passe correctement. En effet, l’éditeur de texte avec lequel a été enregistré le programme effectue ses sauvegardes en utilisant l’encodage UTF-8, alors que, par défaut, les chaînes littérales sont converties en supposant qu’elles sont encodées en Latin-1.
Résultat, les caractères accentués seraient mal interprétés. L’utilisation de
fromUtf8() est une première solution au problème, une autre consiste à invoquer l’instruction suivante juste après la création de l’instance de
QApplication :
#include <QTextCodec>
// .....
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")) ;
Si vous utilisez différents éditeurs pour écrire vos programmes, faites donc attention à l’encodage utilisé lors de l’enregistrement de vos fichiers. Mais revenons à nos moutons.
28 // texte intermédiaire
29 curseur.movePosition(QTextCursor::NextBlock) ;
30 curseur.insertText("Encore du texte...\nListe 2, premier item\n") ;
La ligne 29 nous permet de " sortir " de notre première liste, simplement en déplaçant le curseur vers le bloc suivant – le bloc vide que nous avons pris soin d’insérer (ligne 17) et de conserver après la liste (lignes 23-24).
Le texte inséré ligne 30 ne fait donc partie d’aucune liste. Remarquez la présence des caractères
‘\n’ : chacun provoquera la création d’un nouveau bloc. À l’issue de cette insertion, notre document se termine donc toujours par un bloc vide.
31 // deuxième liste
32 bf.setBackground(Qt::yellow) ;
33 liste_fmt.setStyle(QTextListFormat::ListSquare) ;
34 curseur.movePosition(QTextCursor::Left) ;
35 QTextList* liste_2 = curseur.createList(liste_fmt) ;
36 curseur.mergeBlockFormat(bf) ;
37 curseur.insertBlock() ;
38 curseur.insertText(QString::fromUtf8(„Liste 2, deuxième item")) ;
La ligne 34 positionne le curseur dans l’avant-dernier bloc, qui contient le texte
"Liste 2, premier item" inséré ligne 30.
La ligne suivante crée une nouvelle liste, en faisant du bloc dans lequel se trouve le curseur le premier élément de cette liste. La méthode
createListe() de
QTextCursor est donc un deuxième moyen de créer une liste. Un deuxième élément est ajouté par les lignes 37 et 38. Mais voyons comment créer une " sous-liste ".
39 // troisième liste
40 bf.setBackground(Qt::cyan) ;
41 liste_fmt.setStyle(QTextListFormat::ListCircle) ;
42 liste_fmt.setIndent(2) ;
43 curseur.insertBlock() ;
44 curseur.movePosition(QTextCursor::Left) ;
45 QTextList* liste_3 = curseur.insertList(liste_fmt) ;
46 curseur.mergeBlockFormat(bf) ;
47 curseur.insertText(„Liste 3, premier item\n“) ;
48 curseur.insertText(QString::fromUtf8(„Liste 3, deuxième item")) ;
La procédure est en fait assez similaire à celle utilisée pour insérer une liste dans le cours normal du texte. On commence par insérer un bloc (ligne 43), créant ainsi un nouvel item vide dans la liste 1. Puis, le curseur est déplacé d’un cran vers la gauche (ligne 44), ce qui le positionne à la fin de l’avant-dernier item. Enfin, la sous-liste est insérée normalement (ligne 45). Le curseur est alors " dans " la sous-liste, que nous pouvons manipuler comme précédemment. Remarquez le changement d’indentation pour le style appliqué à cette sous-liste, ligne 42, par la méthode
setIndent() de
QTextListFormat. Il n’existe malheureusement pas de méthode permettant d’ajuster précisément la dimension de cette indentation : le paramètre est simplement interprété comme un niveau de profondeur dans la hiérarchie.
49 // deuxième liste à nouveau
50 curseur.movePosition(QTextCursor::Right) ;
51 curseur.insertText(QString::fromUtf8("Liste 2, troisième item")) ;
52 // fin
53 curseur.movePosition(QTextCursor::Right) ;
54 curseur.insertText("Fin.") ;
55 te.show() ;
56 return app.exec() ;
57 }
Pour sortir de la sous-liste et retourner dans la liste qui la contient, il suffit de déplacer le curseur vers la droite (ligne 50), dans la mesure où il se trouve à la fin du dernier élément.Dernier mot, la méthode
currentList() de
QTextCursor retourne un pointeur sur la liste dans laquelle se trouve le curseur, ou 0 si le curseur n’est dans aucune liste.
Les tableaux
Nous allons, pour cet exemple, nous rapprocher d’un petit éditeur de texte, offrant la possibilité d’insérer et de manipuler des tableaux dans un document. Voici l’interface que nous allons créer :

Le contenu du document a été saisi manuellement, mais il aurait également pu être construit par programmation. Voyons comment s’organise ce programme tout simple :
tableaux_main_win.h et tableaux_main_win.cpp, déclaration et implémentation de la fenêtre principale ;
tableaux.cpp pour la fonction main() ;
tableaux.pro pour référencer tout cela et laisser le soin à qmake de générer les commandes de compilation qui vont bien.
La structure est tout à fait classique, aussi nous ne nous y attarderons pas. Intéressons-nous d’abord à la méthode permettant d’insérer un tableau :
39 void MainWin::insererTableau()
40 {
41 QTextCursor curseur = _editeur->textCursor() ;
42 QTextTableFormat fmt ;
43 fmt.setAlignment(Qt::AlignHCenter) ;
44 curseur.insertTable(2, 3, fmt) ;
45 }
Première chose, récupérer le curseur courant de l’éditeur par la méthode
textCursor() de
QTextEdit (ligne 41). Ensuite, on prépare une mise en forme pour notre tableau, représentée par une instance de
QTextTableFormat.
Celle-ci permet de spécifier certaines caractéristiques, comme l’alignement du tableau dans la page (centré ici), l’espace entre les cellules, forcer les largeurs de certaines colonnes, etc.
Puis, le tableau est inséré à l’aide de
insertTable() de
QTextCursor, qui retourne un pointeur sur une instance de
QTextTable. Le premier paramètre est le nombre de lignes, le deuxième le nombre de colonnes, le troisième (optionnel) la mise en forme à appliquer. Si nécessaire, le paragraphe contenant le curseur est coupé en deux pour laisser la place au tableau. Tout cela est en fait désespérant de facilité.
Voici maintenant la méthode insérant une ligne au tableau :
64 void MainWin::insererLigne()
65 {
66 QTextCursor curseur = _editeur->textCursor() ;
67 QTextTable* tableau = curseur.currentTable() ;
68 if ( tableau == 0 )
69 return ;
70 QTextTableCell cellule = tableau->cellAt(curseur) ;
71 tableau->insertRows(cellule.row(), 1) ;
72 }
L’insertion d’une ligne dépend naturellement de la position du curseur : on commence donc par le récupérer (ligne 66). La ligne 67 permet d’obtenir le tableau dans lequel se trouve le curseur. S’il ne se trouve dans aucun, inutile de continuer (lignes 68-69). Sinon, la méthode
cellAt() de
QTextTable nous donne la cellule dans laquelle se trouve le curseur, sous la forme d’une instance de
QTextTableCell. Cette classe donne différentes informations concernant une cellule, comme ses coordonnées ou son étendue (en effet les cellules peuvent s’étendre sur plusieurs lignes ou colonnes), mais surtout elle donne un moyen d’obtenir un curseur sur son contenu, par les méthodes
firstCursorPosition() et
lastCursorPosition().
L’insertion d’une ligne se fait simplement en invoquant la méthode
insertRows() de
QTextTable, le premier paramètre étant l’indice de la ligne avant laquelle effectuer l’insertion, le deuxième étant le nombre de lignes à insérer.
L’insertion d’une (ou plusieurs) colonne(s) est réalisée par
insertColumns(), tandis que les suppressions sont effectuées par
removeRows() (pour les lignes) et
removeColumns() (pour les colonnes). Fait intéressant, les cellules d’un tableau peuvent contenir pratiquement n’importe quoi : plusieurs blocs, d’autres tableaux imbriqués, des listes... Il est donc possible de réaliser des constructions assez complexes.
Conclusion
Voilà pour cet aperçu des possibilités de mises en forme des éléments d’un document. Nous avons passé sous silence les mises en forme des cadres (de type
QTextFrame) au moyen de la classe
QTextFrameFormat : les principes sont tout à fait similaires, consultez la documentation de Qt pour plus de détails.
La prochaine fois, nous aborderons un sujet important, négligé dans la série précédente consacrée à Qt3, à savoir l’utilisation de l’outil graphique de conception d’interface fourni avec Qt, QtDesigner.
Références
[1] boost::any :
http://www.boost.org/doc/html/any.html
Donnez votre avis
Vous devez avoir ouvert une session pour écrire un commentaire.