Qt4 : Mise en forme de textes
icone programmation
Signature :
GNU/Linux Magazine
Sommaire de l'article :

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 :

/img-articles/lm/84/art-7/fig-1.jpg

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 :

/img-articles/lm/84/art-7/fig-2.jpg

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 :

/img-articles/lm/84/art-7/fig-3.jpg

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 :

/img-articles/lm/84/art-7/fig-4.jpg

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
Il y a : 0 commentaire(s)

Donnez votre avis

Vous devez avoir ouvert une session pour écrire un commentaire.

Brèves
Édito : Linux Pratique Essentiel N°24
Édito : Linux Pratique HS N°23
Édito : GNU/Linux Magazine 146
Édito : GNU/Linux Magazine HS N°58
Édito : Open Silicium N°5
Communication
Linux Pratique HS 23 – Communiqué de presse
Linux Pratique Essentiel N°24 – Communiqué de presse
Gnu/Linux Magazine sponsor et partenaire de PROLOGIN
Linux Essentiel partenaire des Rencontres du Libre de Lion sur Mer (Normandie)
GNU/Linux Magazine HS 58 – Communiqué de presse
prochainement moteur de recherches des articles
 
:
:
Jours heures minutes secondes
En kiosque
Le tout nouveau Linux Pratique Essentiel est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Linux Pratique est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine HS est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Open Silicium est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Linux Pratique est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Misc est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...