开发者

QDockWidget behavior when changing its content

I'm facing a problem with one of my QDockWidget. I have several QWidget items in a QDockwidget that are sometimes visible sometimes not.

I would like that my QDockWidget resizes itself depending on its content... Not only when QWidgets appear in it, but also when they disappear...

So far,开发者_开发百科 my QDockWidget resizes itself when more QWidgets are displayed in it, but when I make them disappear, the QDockWidget stays at his previous size...

Any ideas to help ?

Thanks in advance!


There have been various posts over the years regarding control of the size of a QDockWidget in a QMainWindow dock area. I, too, have been struggling with this issue and have only been able to achieve a partial, and somewhat unsatisfactory, solution. The main problem (if you'll excuse the pun) is the inability to get a grip on the docking mechanism from the context of the QMainWindow that does the work of managing its dock areas. Attempts to use layout management - size policy and size hint controls - are not effective; the QMainWindow does its own thing when changing dock area sizes.

First, what limited success I have had:

Starting with a QMainWindow subclass (MW) and a QDockWidget subclass (DW). The DW has a QWidget, with a QHBoxLayout, that is setWidget in the DW. This layout has two widgets - I'll call them panels - with one of these panels intended to be shown or hidden depending on context: shown when the DW is in the bottom or top dock areas or floating, hidden otherwise. The sizeHint of the other panel after construction is used (along with appropriate margin spacing) to set the "base size" of the DW, with the constructed sizeHint width of the panel that will change visibility providing the increment to the base size when appropriate: the DW implementation is provided with a panel_visible method that is used to enable or disable the variable panel by applying setVisible to the panel and changing the value of the sizeHint by the increment value. The size policy of the DW and its panels are set to Minimum.

In the MW the DW dockLocationChanged and topLevelChanged signals are connected to a DW_resize slot. Here, when the DW isVisible, isWindow is false and MW::dockWidgetArea reports either LeftDockWidgetArea or RightDockWidgeArea, DW::panel_visible(false) is called to change the effective DW size (when the above conditions are not met DW::panel_visible(true) is called, of course). Invoking DW::resize, and updateGeometry and update in the MW has no effect on the dock area size. However if DW::setMaximumSize(DW::sizeHint()) is called the dock area is correctly resized (no updateGeometry or update needed). This works as desired when the DW is floated (by dragging or double-clicking its title bar) and then redocked (by double-clicking its title bar or dragging it back over a side dock area). So far, so good.

Now the catch:

Having coerced the MW to fit its dock area to the prescribed DW size the DW needs to be released from its fixed size constraint so the user can resize the dock area by dragging the spit handle provided by the MW between to the dock area and the central area. The obvious answer is to just call DW::setMaximumSize(0xFFFFFF, 0xFFFFFF) to "release" the DW constraints. Yes, except that update painting optimization that goes on behind the scenes coalesces the two sizing events with the result that the initial dock shrink action is lost. By putting a qApp->sendPostedEvents() and qApp->flush() between the two setMaxmimumSize calls this optimizing effect is avoided, the dock area is fit to the DW size and then left released so the dock area can be resized by the user ... sometimes.

This solution works when the DW goes from floating to docked by double-clicking the DW title bar, but not when the DW is dragged to a side dock in the MW. So, for example, if the user drags the DW from the left dock to the right dock the right dock area is not resized as expected; the receiving dock area remains the size of the floating DW that is produced during the drag from one side to another. If the DW in the receiving dock area has its title bar double-clicked (to become floating again) and then double-clicked again (to return it to the same dock area) the MW now fits the dock area as intended. On close inspection - by monitoring the MW::paintEvent - I see that when the dock area ends up the intended size the flush() is immediately followed by a paintEvent where the DW reports having the intended size and after the second setMaximumSize that unconstrains the DW a paintEvent occurs with the DW still the intended sized. But when the DW is dragged into the dock area the flush() is again immediately followed by paintEvent where the DW reports having the intended size, but after the second setMaximumSize in this case there are two paintEvents with the DW now surprisingly having its previous floating size!

I have yet to find a way to prevent this unexplained overriding of the DW size after it has been correctly sized. It seems clear that an additional resize event is being generated by the MW after the DW_resize slot processing has returned, from size information that the MW has been holding from before the signals were emitted that lead to the slot. Monitoring the MW::eventFilter does indeed reveal a Resize event occurring after DW_resize has returned that changes the DW size from what it had been set to in the slot code back to its size when it was floating. When double-clicking the DW tile bar is used to move the DW from floating back into the side dock no additional Resize event occurs after the DW_resize slot returns.

The challenge, then, is how to prevent the unexpected resize reversion from happening after the DW has been correctly sized in the DW_resize slot. Perhaps some coercion in DW::resizeEvent will avoid this problem ....

Better, of course, would be if the Qt developers would provide the application developer thorough controls in the QMainWindow API over its dock management activities - especially dock area sizing - and/or access to the widgets that it uses for dock area management.

I am currently using Qt 4.6.2 on Linux, OS X and MS/Windows. The debug reports, above, were done on an Intel OS X 10.6.7 system; results differ somewhat on the different platforms, but the basic problem is the same. Perhaps these QMainWindow/QDockWidget issues have been dealt with in a later version of Qt? Perhaps someone has deeper insight into what is going on here and can offer a simple solution?


I have been having the same problem. Inexplicably putting restoreState() twice has solved it for me.
I'm using Qt 4.7.0.

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

static bool first = true;

if (first){
   restoreState(...);
   restoreState(...);
   first = false;
}
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜