Contents Up Previous Next

Vue d'ensemble des contraintes

Classes: wxLayoutConstraints, wxIndividualLayoutConstraint.

Note: les contraintes sont maintenant obsolètes, et vous devriez utiliser les sizers à la place.

Les objets de classe wxLayoutConstraint peuvent être associés avec une fenêtre pour définir la mise en page, en fonction des autres contrôles ou parents.

Cette rubrique est composée des huit contraintes de classe wxIndividualLayoutConstraint suivantes, certaines, ou toutes, peuvent être utilisées directement pour placer les contraintes appropriées.

Les contraintes sont initialement réglées de façon à avoir une relation wxUnconstrained, ce qui signifie que leurs valeurs doivent être calculées en regardant les contraintes connues. Pour calculer la position et la taille d'un des contrôles, l'algorithme de mise en page a besoin de connaître exactement 4 contraintes (comme il a 4 nombres à calculer à partir des contraintes), vous devriez donc toujours régler 4 des contraintes dans la table ci-dessus.

Si vous voulez que la hauteur et la largeur des contrôles aient la valeur par défaut, vous devez utiliser une valeur spéciale pour la contrainte : wxAsIs. Si la contrainte est wxAsIs, la dimension ne sera pas changée, ce qui est utile pour les contrôles des boites de dialoge qui ont souvent la taille par défaut (par exemple, les boutons dont la taille est déterminée par leur texte).

Le calcul des contraintes est fait dans la fonction wxWindow::Layout qui évalue les contraintes. Pour l'appeler, vous pouvez soit appeler wxWindow::SetAutoLayout si la fenêtre parente est une frame, un panel ou une boite de dialogue, pour indiquer au gestionnaires OnSize d'appeler Layout automatiquement quand la taille de la fenêtre change, ou alors surclasser OnSize et appeler Layout vous même (notez que vous devez appeler Layout vous même si la fenêtre parente n'est pas une frame, un panel ou une boite de dialogue).

Plus de détails sur la mise en page par contraintes
Exemples de mises en page de fenêtres


Plus de détails sur la mise en page par contraintes

Par défaut, les fenêtres n'ont pas d'objet wxLayoutConstraints. Dans ce cas, la mise en page doit être faite explicitement, en effectuant des calculs dans les membres OnSize, excepté dans le cas de frames qui n'ont qu'une seule sous-fenêtre (hormis la barre d'outils et la barre d'état qui sont également positionnées par la frame automatiquement), où wxFrame::OnSize s'occupe de redimensionner le contrôle enfant de façon à ce qu'il tienne toute la fenêtre.

Pour éviter d'avoir à d'effectuer tous ces calculs, l'utilisateur peut créer un objet wxLayoutConstraints et l'associer à sa fenêtre avec wxWindow::SetConstraints. Cet objet contient une contrainte pour chacun des bords de la fenêtre, deux pour le point central, et deux pour la taille de la fenêtre. En définissant certaines ou toutes ces contraintes correctement, l'utilisateur peut effectuer des mises en page complexes en définissant des relations complexes entre les fenêtres.

Avec wxWidgets, chaque fenêtre peut être contrainte relativement à ses contrôles frères dans la même fenêtre, ou le contrôle parent. L'algorithme de mise en page fonctionne donc de manière 'top-down' (du haut vers le bas), trouvant la mise en page correcte pour les enfants d'une fenêtre, puis la mise en page pour les petits enfants, ainsi de suite. Notez que cela diffère sensiblement de lamise en page native de Motif, où les contraintes peuvent partir vers le haut et peuvent éventuellement modifier la taille de la frame, du panel ou de la boite de dialogue. Nous supposons dans wxWidgets que l'utilisateur est toujours le 'patron' et qu'il spécifie la taille de la fenêtre extérieures, à laquelle doivent s'adapter les sous-fenêtres. De toute évidence, cela peut être un limitation dans certaines circonstances, mais cela et préférable dans la majorité des situations, et la simplification permet d'éviter certains des problèmes cauchemardesques associés à la programmation sous Motif.

Quand l'utilisateur défini des contraintes, beaucoup de contraintes pour les bords et les dimensions des fenêtres restent non-contraints. Pour une fenêtre donnée, l'algorithm wxWindow::Layout réinitialise toutes les contraintes dans tous les enfants afin d'obtenir des valeurs inconnues, et ensuite, itère à travers les contraintes, afin de les évaluer. Pour les bord et dimensions non contraints, il essaye de trouver la valeur en utilisant les relations qui sont toujours restées. Par exemple, une largeur (width) non contrainte peut être calculée à partir des bords gauche (left) et droit (right), si les deux sont actuellement connus. Pour les bords et dimensions avec des contraintes fournies par l'utilisateur, ces contraintes sont évaluées si les entrées des contraintes sont connues.

L'algorithme s'arrête quand tous les bords et dimensions des contrôles enfants sont connus (succès), ou s'il y a des bords ou dimensions inconnus mais il n'y a eut aucun changement dans ce cycle (échec).

ensuite, il définit toutes les positions et tailles par rapport aux valeurs qu'il a trouvé.

Du fait que l'algorithme soit itératif, l'ordre dans lequel les contraintes sont prises en compte n'est pas pertinent, mais vous pouvez réduire le nombre d'itérations (et donc accélérer les calculs de mise en page) en créant les contrôles dans un ordre qui permet le calcul du plus de contraintes possible pendant la première itération. Par exemple, si vous avez deux boutons que vous voulez positionner dans le coin inférieur droit, il est légèrement plus efficace de créer d'abord le second bouton en spécifiant que son bord droit IsSameAs(parent, wxRight) (en gros, qu'il est au même endroit que le bord droit dela fenêtre parente), et ensuite, de créer le premier bouton en spécifiant qu'il doit être LeftOf() (à gauche) du second, plutôt que de les créer dans un ordre naturel "de gauche à droite".


Exemples de mises en page de fenêtres


Exemple 1: mise en page de sous-fenêtres

Cet exemple crée un panel et une fenêtre côte-à-côte, avec une sous-fenêtre texte en dessous.

  frame->panel = new wxPanel(frame, -1, wxPoint(0, 0), wxSize(1000, 500), 0);
  frame->scrollWindow = new MyScrolledWindow(frame, -1, wxPoint(0, 0), wxSize(400, 400), wxRETAINED);
  frame->text_window = new MyTextWindow(frame, -1, wxPoint(0, 250), wxSize(400, 250));

  // Définition des contraintes pour la sous-fenêtre panel
  wxLayoutConstraints *c1 = new wxLayoutConstraints;

  c1->left.SameAs       (frame, wxLeft);
  c1->top.SameAs        (frame, wxTop);
  c1->right.PercentOf   (frame, wxWidth, 50);
  c1->height.PercentOf  (frame, wxHeight, 50);

  frame->panel->SetConstraints(c1);

  // Définition des contraintes pour la sous-fenêtre scrolledwindow
  wxLayoutConstraints *c2 = new wxLayoutConstraints;

  c2->left.SameAs       (frame->panel, wxRight);
  c2->top.SameAs        (frame, wxTop);
  c2->right.SameAs      (frame, wxRight);
  c2->height.PercentOf  (frame, wxHeight, 50);

  frame->scrollWindow->SetConstraints(c2);

  // Définition des contraintes pour la sous-fenêtre texte
  wxLayoutConstraints *c3 = new wxLayoutConstraints;
  c3->left.SameAs       (frame, wxLeft);
  c3->top.Below         (frame->panel);
  c3->right.SameAs      (frame, wxRight);
  c3->bottom.SameAs     (frame, wxBottom);

  frame->text_window->SetConstraints(c3);

Exemple 2: mise en page d'un élément panel

Cet exemple dimensionnes un bouton à 80% de la largeur du panel, et le centre horizontalement. une zone de liste et un élément texte sont placés en dessous. La zone de liste prend jusqu'à 40% de la largeur du panel, et l'élément texte utilisera le reste de la largeur. des marges de 5 pixels sont également utilisées.

  // Créer les éléments du panel
  wxButton *btn1 = new wxButton(frame->panel, -1, "A button") ;

  wxLayoutConstraints *b1 = new wxLayoutConstraints;
  b1->centreX.SameAs    (frame->panel, wxCentreX);
  b1->top.SameAs        (frame->panel, wxTop, 5);
  b1->width.PercentOf   (frame->panel, wxWidth, 80);
  b1->height.PercentOf  (frame->panel, wxHeight, 10);
  btn1->SetConstraints(b1);

  wxListBox *list = new wxListBox(frame->panel, -1, "A list",
                                  wxPoint(-1, -1), wxSize(200, 100));

  wxLayoutConstraints *b2 = new wxLayoutConstraints;
  b2->top.Below         (btn1, 5);
  b2->left.SameAs       (frame->panel, wxLeft, 5);
  b2->width.PercentOf   (frame->panel, wxWidth, 40);
  b2->bottom.SameAs     (frame->panel, wxBottom, 5);
  list->SetConstraints(b2);

  wxTextCtrl *mtext = new wxTextCtrl(frame->panel, -1, "Multiline text", "Some text",
                        wxPoint(-1, -1), wxSize(150, 100), wxTE_MULTILINE);

  wxLayoutConstraints *b3 = new wxLayoutConstraints;
  b3->top.Below         (btn1, 5);
  b3->left.RightOf      (list, 5);
  b3->right.SameAs      (frame->panel, wxRight, 5);
  b3->bottom.SameAs     (frame->panel, wxBottom, 5);
  mtext->SetConstraints(b3);