2010-06-20 6 views
2

Je suis confronté à un problème avec l'un de mes QDockWidget. J'ai plusieurs QWidget articles dans un QDockwidget qui sont parfois visibles parfois non.Comportement de QDockWidget lors de la modification de son contenu

Je voudrais que mon QDockWidget se redimensionne en fonction de son contenu ... Non seulement quand QWidgets y figurent, mais aussi quand ils disparaissent ...

Jusqu'à présent, mon QDockWidget se redimensionne lorsque plus QWidgets sont affiché en elle, mais quand je les fais disparaître, le QDockWidget reste à sa taille précédente ...

Des idées pour vous aider?

Merci d'avance!

Répondre

6

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 DWdockLocationChanged et topLevelChanged sont reliés à une fente DW_resize. Ici, lorsque le DWisVisible, 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?

+0

Réponse étonnante, merci beaucoup pour votre copain de temps! –

0

J'ai eu le même problème. Inexplicablement mettre restoreState() deux fois l'a résolu pour moi.
J'utilise Qt 4.7.0.

void MainWnd::showEvent(QShowEvent *se){ 
QMainWindow::showEvent(se); 

static bool first = true; 

if (first){ 
    restoreState(...); 
    restoreState(...); 
    first = false; 
} 
} 
Questions connexes