Programmation Qt/Le positionnement des widgets

Un livre de Wikilivres.
Sauter à la navigation Sauter à la recherche

Le positionnement des widgets est essentiel dans Qt. Nous travaillerons avec le positionnement absolu, et le plus utilisé, le positionnement relatif.

Le positionnement absolu[modifier | modifier le wikicode]

Le positionnement absolu est celui que nous avons vu jusqu'ici. Nous le reverrons en détail.

Utiliser le positionnement absolu[modifier | modifier le wikicode]

Nous avons plusieurs méthodes pour utiliser le positionnement absolu.

  • monWidget->move(50, 70); déplace le widget à l’abscisse (x) 50 et l'ordonnée (y) 70. Les attributs sont exprimées en pixels.
  • monWidget->setSize(24, 89); redimensionne le widget de 24 pixels de largeur et de 89 pixels de hauteur.
  • monWidget->setGeometry(50, 70, 24, 89); déplace le widget à l'abscisse 50 et à l'ordonnée 70 tout en lui donnant une largeur de 24 et une hauteur de 89.

Les défauts du positionnement absolu[modifier | modifier le wikicode]

Malheureusement, le positionnement absolu comporte des défauts. Essayez de redimensionner la fenêtre pour qu'elle soit la plus petite possible. Votre widget va se couper, ou bien, si vous faites une trèèès petite fenêtre, va disparaître ! C'est pour cela que nous allons découvrir un nouveau positionnement, le positionnement relatif.

Logo Si vous utilisez la méthode setFixedSize(), vous pouvez utiliser le positionnement absolu. C'est comme cela que fonctionne certains jeux.


Le positionnement relatif[modifier | modifier le wikicode]

Eh bien, l'heure est venue de découvrir le positionnement relatif. On utilisera 4 classes issus de QLayout : QHBoxLayout et QVBoxLayout, issues de la classe QBoxLayout (classe abstraite), QGridLayout et QFormLayout.

Principe des layouts[modifier | modifier le wikicode]

Le principe des layouts est simple : les widgets s'adaptent à la taillent de la fenêtre. Pour cela, ils utilisent des "grilles", numérotées :

Principe des layouts
0, 0 1, 0 ...
0, 1 1, 1 ...
... ... ...

Maintenant, attaquons-nous au code.

QHBoxLayout : layout horizontal[modifier | modifier le wikicode]

Dans ce premier layout, nous allons découvrir quelques méthodes, qui s'utiliseront aussi pour les autres layouts. Imaginons que vous voulez des boutons.

 1 QWidget *maPage = new QWidget(); /* Création de la page qui contiendra le layout */
 2 
 3 /* Création des boutons */
 4 QPushButton *bouton1 = new QPushButton("Wiki");
 5 QPushButton *bouton2 = new QPushButton("Books");
 6 
 7 QHBoxLayout *monLayout = new QHBoxLayout(); /* Création du layout */
 8 /* Ajout des widgets dans le layout */
 9 monLayout->addWidget(bouton1);
10 monLayout->addWidget(bouton2);
11 
12 maPage->setLayout(monLayout); /* Le layout appartient désormais à l'objet maPage */

On remarque les méthodes :

  • addWidget() : ajout d'un widget dans le layout.
  • setLayout() : définition du layout pour le widget demandé.

QVBoxLayout : layout vertical[modifier | modifier le wikicode]

Le fonctionnement de QVBoxLayout est le même que QHBoxLayout, à l’exception que cette fois-ci, c'est à la verticale. Autrement dit, je peux vous laisser remplacer les noms de classes.

QGridLayout : un layout en grille[modifier | modifier le wikicode]

OOjs UI icon helpNotice-ltr-progressive.png C'est bien gentil, mais comment pourrais-je faire quand j'aurais beaucoup de widgets ?

C'est là qu'intervient QGridLayout : un layout en grille, comme le schéma du principe des layouts plus haut dans la page. Notre belle méthode addWidget() va se transformer :

 1 QPushButton *wi = new QPushButton("Wi"); /* Création des boutons */
 2 QPushButton *ki = new QPushButton("ki");
 3 QPushButton *books = new QPushButton("books");
 4 
 5 /* Introduction des boutons dans le layout */
 6 QGridLayout *m_layout = new QGridLayout();
 7 m_layout->addWidget(wi, 0, 0); /* En haut à gauche */
 8 m_layout->addWidget(ki, 1, 0); /* En haut à droite */
 9 m_layout->addWidget(books, 1, 1, 1, 2); /* En bas */
10 
11 /* Introduction du layout dans la page */
12 QWidget *m_page = new QWidget();
13 m_page->setLayout(m_layout);

Les deux premiers boutons sont tous les deux en haut, l'un à gauche et l'autre à droite. Mais le troisième bouton, lui est entièrement en bas car nous avons inséré deux nouveaux chiffres : rowSpan et columnSpan. On dit donc que le widget doit prendre 1 ligne en hauteur et 2 colonnes en largeur.

Logo En réalité, il existe, comme on peut le voir dans la documentation, deux méthodes addWidget(). La première accepte le widget à insérer, puis les coordonnées. La deuxième, quant à elle, accepte le widget, la position x, la position y, la hauteur (rowSpan) et la largeur (columnSpan).


QFormLayout : un layout pour formulaire[modifier | modifier le wikicode]

Il se peut qu'un jour, vous voudriez mettre vos formulaires dans un layout. Mais c'est très long. C'est pour cela que QFormLayout à été créé : un layout spécialement fait pour les formulaires. Voici comment on s'en sert :

 1 /* Création des widgets */
 2 QLineEdit *nom = new QLineEdit();
 3 QLineEdit *langageProg = new QLineEdit();
 4 
 5 /* Création et introduction dans le layout */
 6 QFormLayout *monLayout = new QFormLayout();
 7 monLayout->addRow("Votre nom : ", nom);
 8 monLayout->addRow("Votre langage de programmation préféré : " langageProg);
 9 
10 /* Création et introduction dans la page **/
11 QWidget *maPage = new QWidget();
12 maPage->setLayout(monLayout);

Ce layout fonctionne de la manière suivante : avec la méthode addRow(), on met le libellé du champ et le nom du champ.

Logo C'est bien addRow() et non addWidget() comme les autres layouts.


Combiner les layouts[modifier | modifier le wikicode]

OOjs UI icon helpNotice-ltr-progressive.png Et comment je fais si je veux mettre un bouton Quitter à mon formulaire ?

C'est pour cela qu'on peut les combiner ! Et c'est ce principe là, qui fait la force des layouts. Ainsi, vous pouvez disposer vos widgets partout dans la page quelques soient vos envies.

 1 QLineEdit *nom = new QLineEdit();
 2 QLineEdit *prenom = new QLineEdit();
 3 
 4 QFormLayout *layoutFormulaire = new QFormLayout();
 5 layoutFormulaire->addRow("Votre nom : ", nom);
 6 layoutFormulaire->addRow("Votr prénom : ", prenom);
 7 
 8 QPushButton *boutonQuitter = new QPushButton("Quitter");
 9 
10 QVBoxLayout *layoutPrincipal = new QVBoxLayout();
11 layoutPrincipal->addLayout(layoutFormulaire); /* Utilisation de la méthode addLayout() */
12 layoutPrincipal->addWidget(boutonQuitter);
13 
14 QWidget *maPage = new QWidget();
15 maPage->setLayout(layoutPrincipal);

On observe que la méthode pour combiner les layouts est addLayout().

Logo La méthode addLayout() existe uniquement pour les QHBoxLayout, QVBoxLayout et QGridLayout. N'utilisez donc pas cette méthode avec QFormLayout !

En résumé[modifier le wikicode]

  • Il existe deux positionnements : le 'positionnement absolu et le positionnement relatif. L'absolu a plusieurs défauts qui sont réglés dans le relatif, mais il est parfois plus utile que le relatif.
  • Les layouts sont à la base du positionnement relatif : ils contiennent tous les widgets selon un plan précis.
  • Les layouts QHBoxLayout et QVBoxLayout sont des layouts n'opérant que sur un seul axe ; il revient néanmoins plus utile dans certaines situations. On utilise la méthode addWidget() pour insérer un widget.
  • Le layout de grille combine les layouts horizontaux et verticaux. Il s'utilise avec la classe QGridLayout. Là aussi, la méthode addWidget() s'utilise, mais avec quelques modifications : on y indique désormais le numéro de ligne et de colonne, et dans certains cas, le nombre de lignes ou de colonnes qu'occupe un seul widget ; on parle alors de spaning.
  • Le layout de formulaire, utilisé avec QFormLayout, est spécialement conçu pour les formulaires. On y ajoute un champ avec la méthode addRow(label, widget).
  • Enfin, les layouts se fortifient quand on les combine, avec la méthode addLayout(), de même structure que addWidget().