Il y a eu divers messages au cours des années concernant le contrôle de la taille d'un QDockWidget
dans une zone de dock QMainWindow
. Moi aussi, j'ai été aux prises avec ce problème et j'ai seulement réussi à trouver une solution partielle et quelque peu insatisfaisante. Le problème principal (si vous excusez le jeu de mots) est l'incapacité de maîtriser le mécanisme d'amarrage dans le contexte de la QMainWindow
qui fait le travail de gestion de ses zones de dock. Les tentatives d'utilisation de la gestion de la mise en page - règle de taille et contrôles d'indice de taille - ne sont pas efficaces; le QMainWindow
fait sa propre chose en changeant les tailles de zone de dock.
D'abord, ce qui limite le succès que j'ai eu:
A partir d'une sous-classe QMainWindow
(MW
) et une sous-classe QDockWidget
(DW
). Le DW
a un QWidget
, avec un QHBoxLayout
, soit setWidget
dans le DW
. Cette disposition a deux widgets - je les appellerai des panneaux - avec un de ces panneaux destiné à être montré ou caché selon le contexte: montré quand le DW
est dans les zones inférieures ou supérieures de dock ou flottant, caché autrement. Le sizeHint
de l'autre panneau après construction est utilisé (avec marge appropriée) pour définir la "taille de base" du DW
, avec la largeur sizeHint
construite du panneau qui changera la visibilité en fournissant l'incrément à la taille de base le cas échéant: l'implémentation DW
est fournie avec une méthode panel_visible
qui est utilisée pour activer ou désactiver le panneau de variables en appliquant setVisible au panneau et en modifiant la valeur du sizeHint
par la valeur de l'incrément. La stratégie de taille du DW
et de ses panneaux est définie sur Minimum.
Dans le MW
les signaux DW
dockLocationChanged
et topLevelChanged
sont reliés à une fente DW_resize
. Ici, lorsque le DW
isVisible
, isWindow
est faux et MW::dockWidgetArea
rapports soit LeftDockWidgetArea
ou RightDockWidgeArea
, DW::panel_visible(false)
est appelé à changer la taille DW
efficace (lorsque les conditions ne sont pas remplies DW::panel_visible(true)
est appelé, bien sûr). L'appel de DW::resize
et updateGeometry
et update
dans le MW
n'a aucun effet sur la taille de la zone de connexion. Cependant si DW::setMaximumSize(DW::sizeHint())
est appelée la zone de dock est correctement redimensionnée (pas updateGeometry
ou update
nécessaire). Cela fonctionne comme souhaité lorsque le DW
est flottant (en faisant glisser ou en double-cliquant sur sa barre de titre), puis redocké (en double-cliquant sur sa barre de titre ou en le faisant glisser sur une zone de dock latérale). Jusqu'ici tout va bien.
Maintenant, le hic:
Après avoir contraint le MW
à adapter sa zone de quai au prescrit DW
la taille des DW
doit être libéré de sa contrainte de taille fixe, de sorte que l'utilisateur peut redimensionner la zone de station d'accueil en faisant glisser la poignée de la broche fourni par le MW
entre la zone de quai et la zone centrale. La réponse évidente est d'appeler simplement DW::setMaximumSize(0xFFFFFF, 0xFFFFFF)
pour "libérer" les contraintes DW
. Oui, sauf que l'optimisation de la mise à jour de la peinture qui se déroule en coulisse fusionne les deux événements de dimensionnement, ce qui entraîne la perte de l'action initiale de réduction du Dock. En mettant un qApp->sendPostedEvents()
et qApp->flush()
entre les deux appels setMaxmimumSize
cet effet d'optimisation est évité, la zone de dock est ajustée à la taille DW
, puis laissé à gauche afin que la zone de dock peut être redimensionnée par l'utilisateur ... parfois.
Cette solution fonctionne lorsque l'DW
va de flotter à accosté en double-cliquant sur la barre de titre DW
, mais pas quand le DW
est traîné à un quai latéral dans le MW
. Ainsi, par exemple, si l'utilisateur fait glisser le DW
du dock gauche vers le dock droit, la bonne zone de dock n'est pas redimensionnée comme prévu; la zone du quai de réception reste la taille du DW
flottant qui est produite pendant la traînée d'un côté à l'autre. Si le DW
dans la zone de réception reçoit sa double barre de titre (pour flotter à nouveau) et double-clique à nouveau (pour le renvoyer à la même zone de dock), le MW
correspond maintenant à la zone de dock comme prévu. Lors de l'inspection étroite - en surveillant la MW::paintEvent
- Je vois que lorsque la zone portuaire finit par la taille prévue du flush()
est immédiatement suivie d'une paintEvent
où les DW
rapports ayant la taille voulue et après la seconde setMaximumSize
qui unconstrains le DW
un paintEvent
se produit avec le DW
toujours la taille prévue. Mais quand le DW
se laisse entraîner dans la zone du quai du flush()
est à nouveau immédiatement suivie par paintEvent
où les DW
rapports ayant la taille voulue, mais après la deuxième setMaximumSize
dans ce cas il y a deux paintEvent
s avec la DW
surprenante ayant sa précédente taille flottante !
Je n'ai pas encore trouvé un moyen d'empêcher cette surcharge inexpliquée de la taille DW
après qu'il a été correctement dimensionné. Il semble clair qu'un événement de redimensionnement supplémentaire est généré par le MW
après le retour du traitement de l'emplacement DW_resize
, à partir des informations de taille que le MW
a conservées avant l'émission des signaux qui ont conduit à l'emplacement. La surveillance du MW::eventFilter
révèle en effet qu'un événement Resize se produit après que DW_resize
a été retourné et que la taille de DW
a été modifiée par rapport à ce qu'elle avait été définie dans le code de l'emplacement lorsqu'il était flottant. Lorsque vous double-cliquez sur la barre de pavé DW
pour déplacer le DW
de flottant de retour dans le dock latéral aucun événement de redimensionnement supplémentaire se produit après le retour de logement DW_resize
.
Le défi consiste donc à empêcher la réversion de redimensionnement inattendue après que le DW
a été correctement dimensionné dans l'emplacement DW_resize
. Peut-être une coercition dans DW::resizeEvent
permettra d'éviter ce problème ....Mieux, bien sûr, serait si les développeurs Qt fourniraient au développeur de l'application des contrôles approfondis dans l'API QMainWindow
sur ses activités de gestion de quai - en particulier le dimensionnement de la zone de dock - et/ou l'accès aux widgets qu'il utilise pour la zone de quai la gestion. J'utilise actuellement Qt 4.6.2 sous Linux, OS X et MS/Windows. J'utilise actuellement Qt 4.6.2 sur Linux, OS X et MS/Windows. Les rapports de débogage, ci-dessus, ont été effectués sur un système Intel OS X 10.6.7; les résultats diffèrent quelque peu sur les différentes plates-formes, mais le problème de base est le même. Peut-être que ces problèmes QMainWindow
/QDockWidget
ont été traités dans une version ultérieure de Qt? Peut-être que quelqu'un a un aperçu plus profond de ce qui se passe ici et peut offrir une solution simple?
Réponse étonnante, merci beaucoup pour votre copain de temps! –