I. L'article original▲
Cet article est une adaptation en langue française de How to tile widgets in a multiple document interface application, de Titta Heikkala.
II. Nouvelles actions▲
Tout d'abord, on ajoute les actions qui appelleront les fonctions de repositionnement. Ainsi, on ajoute une action pour chaque fonction dans la classe MainWindow en tant qu'attribut privé :
QAction
*
tileVerticalAct;
QAction
*
tileHorizontalAct;
On ajoute aussi un slot privé pour chaque fonction de réarrangement :
void
tileSubWindowsVertically();
void
tileSubWindowsHorizontally();
Il suffit ensuite d'initialiser les actions et de les connecter aux slots adéquats. Le code suivant dans la méthode createActions() initialise ces actions pour l'application :
tileVerticalAct =
new
QAction
(tr("Tile Vertically"
), this
);
tileVerticalAct->
setStatusTip(tr("Tile the windows vertically"
));
connect
(tileVerticalAct, SIGNAL
(triggered()), this
, SLOT
(tileSubWindowsVertically()));
tileHorizontalAct =
new
QAction
(tr("Tile Horizontally"
), this
);
tileHorizontalAct->
setStatusTip(tr("Tile the windows horizontally"
));
connect
(tileHorizontalAct, SIGNAL
(triggered()), this
, SLOT
(tileSubWindowsHorizontally()));
Ensuite, on ajoute ces actions dans le menu de la fenêtre. Ceci peut se faire dans la méthode updateWindowMenu() où les autres actions seront aussi ajoutées au menu :
windowMenu->
addAction(tileVerticalAct);
windowMenu->
addAction(tileHorizontalAct);
III. Réarrangement des fenêtres▲
Maintenant que l'application est prête à réarranger les sous-fenêtres, on regarde de plus près la méthode tileSubWindowsVertically(). Pour commencer, on vérifie l'existence de sous-fenêtres dans l'aire MDI :
if
(mdiArea->
subWindowList().isEmpty())
return
;
Ensuite, on crée un rectangle qui définit la taille idéale de chacune des sous-fenêtres. Lors d'un réarrangement vertical, la largeur d'une sous-fenêtre sera la largeur de l'aire MDI. Sa hauteur sera fonction de la hauteur de l'aire MDI et du nombre de sous-fenêtres ouvertes. En gros, il suffit de diviser la hauteur de l'aire MDI par le nombre de sous-fenêtres qui sont ouvertes. Ce rectangle peut alors être utilisé pour définir la taille de chaque sous-fenêtre dans la zone MDI.
QPoint
position(0
, 0
);
foreach
(QMdiSubWindow
*
window, mdiArea->
subWindowList()) {
QRect
rect(0
, 0
, mdiArea->
width(),
mdiArea->
height() /
mdiArea->
subWindowList().count());
window->
setGeometry(rect);
window->
move(position);
position.setY(position.y() +
window->
height());
}
Après avoir modifié la dimension de chaque sous-fenêtre, on modifie aussi leur position pour que les fenêtres soient empilées verticalement. Les sous-fenêtres sont empilées de haut en bas, selon leur indice. Par défaut, cet ordre est celui de l'insertion de la sous-fenêtre dans la fenêtre principale. La première sous-fenêtre est déplacée dans le coin haut gauche de la fenêtre principale. Pendant ce temps, la position est ajustée de façon à ce que la fenêtre en cours de traitement se place juste en dessous de la fenêtre précédemment traitée. C'est la seule chose requise pour arranger les fenêtres verticalement.
L'arrangement horizontal des sous-fenêtres sera presque identique ; il faut simplement ajuster la position sur l'axe des abscisses des sous-fenêtres. La hauteur des sous-fenêtres sera celle de la fenêtre principale. Les widgets seront positionnés de gauche à droite selon les index des sous-fenêtres, de manière croissante.
void
MainWindow::
tileSubWindowsHorizontally()
{
if
(mdiArea->
subWindowList().isEmpty())
return
;
QPoint
position(0
, 0
);
foreach
(QMdiSubWindow
*
window, mdiArea->
subWindowList()) {
QRect
rect(0
, 0
, mdiArea->
width() /
mdiArea->
subWindowList().count(),
mdiArea->
height());
window->
setGeometry(rect);
window->
move(position);
position.setX(position.x() +
window->
width());
}
}
IV. Conclusions▲
Alors, pas si compliqué finalement ? Vous pouvez essayer ce code (sources).
V. Remerciements▲
Un tout grand merci à Thibaut Cuvelier et à zoom61 pour leur relecture attentive.