C++ resize a docked Qt QDockWidget programmatically?

筅森魡賤 提交于 2019-11-30 04:34:41

I just went through this same process. After trying far too many permutations of resize(), adjustSize() and friends on dock widgets and their contained widget, none of which worked, I ended up subclassing QListView and adding that sizeHint() method.

Now it works like a charm.

I made it easy: HEADER:

private void setDockSize(QDockWidget *dock, int, int);
  public slots:
  void returnToOldMaxMinSizes();

SOURCE:

QSize oldMaxSize, oldMinSize;

void MainWindow::setDockSize(QDockWidget* dock, int setWidth,int setHeight)
{

    oldMaxSize=dock->maximumSize();
    oldMinSize=dock->minimumSize();

  if (setWidth>=0)
    if (dock->width()<setWidth)
        dock->setMinimumWidth(setWidth);
    else dock->setMaximumWidth(setWidth);
  if (setHeight>=0)
    if (dock->height()<setHeight)
        dock->setMinimumHeight(setHeight);
    else dock->setMaximumHeight(setHeight);

    QTimer::singleShot(1, this, SLOT(returnToOldMaxMinSizes()));
}

void MainWindow::returnToOldMaxMinSizes()
{
    ui->dockWidget->setMinimumSize(oldMinSize);
    ui->dockWidget->setMaximumSize(oldMaxSize);
}

It sounds like the dock widget re-sizes itself to the proper size, considering its child widget. From the QDockWidget documentation (emphasis mine):

A QDockWidget acts as a wrapper for its child widget, set with setWidget(). Custom size hints, minimum and maximum sizes and size policies should be implemented in the child widget. QDockWidget will respect them, adjusting its own constraints to include the frame and title. Size constraints should not be set on the QDockWidget itself, because they change depending on wether it is docked; a docked QDockWidget has no frame and a smaller title bar.

In order to change the size, then, you must re-size the child widget.

EDIT: The Qt documentation can sometimes be misleading when it discusses size hints. Often, it's referring to any kind of resizing, whether performed automatically by the widget or programatically.

Alex Goldberg

This is an old question, but I wanted to chime in to mention that Qt 5.6 introduced the QMainWindow::resizeDocks function to handle this.

Unfortunately, it doesn't work for my use case (moving separator between two QDockWidgets that have been split with QMainWindows::splitDockWidget)

Have you tried calling resize() on the QTextEdit inside your dock widget? You could also try temporarily setting the dock widget's maximum & minimum sizes to the size you want it to be, then restore the original values.

You could do this:

Set a maximum height for your QTextEdit:

m_compilerOutput = new QTextEdit;
m_compilerOutput->setMaximumHeight(100);

And then in the show event of your main window set it back to the old size or something high:

void MainWindow::showEvent(QShowEvent *)
{
   m_compilerOutput->setMaximumHeight(10000);
}

That is all you should need.

user674263

Tests using resize on the QDockWidget::widget() (i.e. the widget that the QDockWidget is managing) do not consistently work as expected.

With a QDockWidget subclass (DW) in which a QWidget with a QHBoxLayout that has two widgets (left-panel and right-panel) added, all of which have had their size policies set to QSizePolicy::Minimum, the DW normally has both panel widgets visible. When the DW is positioned in a side dock an application (QMainWindow) slot handling the DW's dockLocationChanged signal hides left-panel and re-sizes the DW->widget() to the size right-panel. When the DW is programmatically moved to the bottom dock area leftPanel is set visible and the DW fills the full width of the main window (of course). When the DW is then programmatically moved to a side dock area the left-panel is hidden and the DW is re-sized down. This works as intended. However, if the DW is dragged from the bottom dock area to a side dock area, though the left-panel is hidden and the re-size applied as before, the DW is not re-sized down as when the repositioning is done programatically. The DW can be manually re-sized down by dragging the splitter handele between the DW and main window central area. Note that the main window central area is a QWidget having a QHBoxLayout with size polices QSizePolicy::Expanding.

Calling adjustSize on the main window after the DW has been re-sized has no effect. This despite the DW having reimplemented sizeHint to return its minimum size depending on whether left-panel is visible or not.

Either I am missing something in how to control the size of QDockWidget (which, given the difficulty I've had understanding all the interactions amongst the parts of the layout management system, is quite likely), or the QMainWindow is ignoring or overriding the layout instructions that it is being given. Closely examining the event stream during the QDockWidget repositioning operations suggests the latter: After the slot handling the dockLocationChanged signal has done its resizing work and returned to the event loop I can see that the QMainWindow, when user repositioning is done, applies additional re-size operations on the affected QDockWidget thus undoing the application logic that attempts to control the dock size. Something seems amiss in the QMainWindow ....

momo

If the dockWidgets are docked, the sizes are control by their parent. In such cases you can use the QMainWindow::resizeDocks function.

If floating, sizes are determined by their children.Resize children to achieve your purpose.

The resize of dock widgets problem when MainWindow is maximized is described in QTBUG-16252 (https://bugreports.qt.io/browse/QTBUG-16252)

I've found another workaround on it. Works for me on QT 5.4.1 minGW on Windows7. It looks like some widget state restore operations are closely related to QApplication event loop.

DockWidget sizes are restored correctly ONLY when following conditions are met:

  1. restoreGeometry() is called BEFORE entering QApplication::exec() (e.g. in constructor of your MainWindow class)

  2. restoreState() is called AFTER exec() (e.g. via QTimer)

Here is my code:

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);

    //...

    MainWindow mainWindow;
    mainWindow.show();

    return application.exec();
}

MainWindow::MainWindow(...) 
{
    ui->setupUi(this);

    //...
    QTimer* nt = new QTimer(this);

    nt->setSingleShot(true);
    nt->setInterval( 100 );

    connect(nt, SIGNAL(timeout()), SLOT(restoreWidgetSettings()));
    nt->connect(nt, SIGNAL(timeout()), SLOT(deleteLater()));

    nt->start();

    restoreWidgetSettings(true);
}

void MainWindow::restoreWidgetSettings(bool geometryOnly) {

    //...
    QByteArray geometry = getSettings();

    restoreGeometry(geometry);

    if(geometryOnly)
        return;

    //... //create dock widgets here

    restoreState(mainWindowState);

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!