I. L'article original

Les Qt Labs Blogs sont des blogs tenus par les développeurs de Qt, concernant les nouveautés ou les utilisations un peu extrêmes du framework.

Nokia, Qt et leurs logos sont des marques déposées de Nokia Corporation en Finlande et/ou dans les autres pays. Les autres marques déposées sont détenues par leurs propriétaires respectifs.

Cet article est la traduction du billet Anchor layout joins the family of QGraphicsLayout, par jan-arve.

II. Motivation

On observe fréquemment que les dispositions existantes dans Qt ne pouvaient pas toujours faire ce que l'on voulait avec un seul widget : par exemple, la fenêtre « Find dialog » de Qt Linguist.

La boîte de dialogue est constituée de quatre objets fournissant une disposition linéaire et d'un autre objet offrant une disposition en grille pour les cases cochables à l'intérieur du conteneur.

Image non disponible
Qt Designer n'affiche ni la disposition interne du conteneur ni la disposition au plus haut niveau.

De surcroît, pour réussir ce simple arrangement, on doit utiliser trois niveaux de dispositions enchevêtrées.

Heureusement, si vous le concevez avec Qt Desinger, c'est plutôt facile, mais il se peut que vous n'y parveniez pas du premier coup. Bien sûr, sa programmation est une chose bien plus ardue. Les résultats seront probablement loin de l'arrangement proposé par un designer d'interface utilisateur. Nous pensons que la disposition par ancrage restreindra ce manque dans la majorité des cas.

III. Concept

La classe QGraphicsAnchorLayout crée une disposition très flexible ; pourtant, le concept reste simple. En créant une ancre entre deux bords de deux éléments de la disposition, on donne une contrainte à la disposition par ancrage. Dans le cas le plus simple, il ne s'agit que de définir une distance fixe entre deux bords de disposition. Ceci peut être effectué avec les bords gauche, droit, supérieur, inférieur et " central " de chaque élément de la disposition. Plusieurs ancres peuvent aussi être connectées à un même bord. Ceci n'est pas possible avec une disposition linéaire, et avec une disposition en grille, ça ne l'est que partiellement. Cela permet de donner à la disposition la structure qu'elle doit avoir. La disposition essaiera alors de satisfaire les contraintes qui lui ont été spécifiées, éventuellement en agrandissant ou rétrécissant les éléments de cette dernière. On peut aussi configurer chaque ancre de telle sorte qu'elle grandisse ou rétrécisse, quand c'est préférable.

L'interface pour la configuration de la structure de la disposition reflète ce concept. La fonction addAnchor() est tout ce dont on a besoin pour configurer cette structure mais, pour le confort de l'utilisateur, nous avons ajouté quelques fonctions pour ancrer les coins des éléments (fonction « subtilement » nommée addCornerAnchors()) et pour ajuster la taille d'un élément par rapport à un autre (addAnchors()). Ainsi, le code suivant garantira la connexion du bord gauche de l'élément findEdit au bord droit de l'élément findLabel. Dans ce cas, cela signifie qu'il y aura un petit espace entre ces éléments et que sa taille ne changera jamais.

 
Sélectionnez
anchorLayout->addAnchor(findLabel, Qt::RightAnchor, findEdit, Qt::LeftAnchor);

On peut aussi ancrer un élément à un bord de la disposition. Si le bord d'un élément est ancré, directement ou non, à un bord de la disposition, sa géométrie réagira aux changements de la géométrie de la disposition :

 
Sélectionnez
anchorLayout->addAnchor(anchorLayout, Qt::LeftAnchor, findLabel, Qt::LeftAnchor);
anchorLayout->addAnchor(findLabel, Qt::RightAnchor, findEdit, Qt::LeftAnchor);

Bien évidemment, on peut aussi ancrer verticalement des éléments tout en utilisant la même méthode.

Maintenant, avec cette brève introduction, on peut revenir à l'exemple du « Find dialog » de Qt Linguist, donné plus tôt. Il s'avère que l'on peut effectuer le même arrangement avec juste une seule disposition par ancrage.

Voici ce à quoi peut ressembler le code :

 
Sélectionnez
QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
QGraphicsWidget *w = new QGraphicsWidget(0, Qt::Window);
w->setLayout(l);

// label, line edit et bouton " Find Next "
l->addCornerAnchors(l, Qt::TopLeftCorner, findLabel, Qt::TopLeftCorner);
l->addCornerAnchors(findLabel, Qt::TopRightCorner, findEdit, Qt::TopLeftCorner);
l->addCornerAnchors(findEdit, Qt::TopRightCorner, findButton, Qt::TopLeftCorner);
l->addCornerAnchors(findButton, Qt::TopRightCorner, l, Qt::TopRightCorner);
// conteneur
l->addCornerAnchors(l, Qt::BottomLeftCorner, groupBox, Qt::BottomLeftCorner);
l->addCornerAnchors(groupBox, Qt::TopRightCorner, findEdit, Qt::BottomRightCorner);
// bouton " Annuler "
l->addCornerAnchors(findButton, Qt::BottomLeftCorner, cancelButton, Qt::TopLeftCorner);
QGraphicsAnchor *anchor = l->addAnchor(cancelButton, Qt::AnchorBottom, l, Qt::AnchorBottom);
anchor->setSizePolicy(QSizePolicy::Minimum);
l->addAnchor(cancelButton, Qt::AnchorRight, l, Qt::AnchorRight);

// Fini !
scene.addItem(w);

Pour des raisons de simplicité, le code n'inclut pas d'élément dans le conteneur, vu qu'il est plus facile de le faire avec une disposition en grille. Ainsi, la disposition par ancrage a réduit quatre dispositions en une.

On pourrait mentionner beaucoup de choses intéressantes ici, mais ce serait redondant avec ce qui est déjà écrit dans la documentation ; c'est pourquoi je vous suggère d'y jeter un coup d'œil.

IV. Conclusion

La disposition par ancrage a quelques propriétés attrayantes. Pour certains assistants, elle offre une interface de programmation plus intuitive et plus proche de la manière dont le designer d'interface utilisateur le spécifierait. Elle est aussi très flexible : on peut construire des graphes d'ancres de forme libre où un même bord peut être ancré à plusieurs autres bords ; on peut modifier les règles concernant la taille de chaque ancre, ce qui rend les éléments d'espace peu utiles ; on peut aussi modifier l'espacement de telle sorte qu'elle revête une valeur aussi bien positive que négative.

La disposition par ancrage n'est évidemment pas la panacée et, dans un certain nombre de cas, il est préférable d'avoir recours à de simples dispositions linéaires ou en grille. La disposition par ancrage est certes flexible, mais il y a un prix à payer : pour certains arrangements, cette disposition peut requérir un très grand nombre de lignes de code en comparaison avec une disposition linéaire, puisqu'il n'y est pas nécessaire de définir une ancre entre chaque élément, l'ancrage étant implicitement déterminé par l'ordre des éléments.

Merci à Thibaut Cuvelier pour son aide à la traduction et à Sébastien Germez pour la relecture orthographique !