C ++以编程方式调整停靠的Qt QDockWidget的大小?

时间:2010-04-27 16:18:27

标签: c++ qt resize qdockwidget

我刚刚开始研究新的C ++ / Qt项目。它将是一个基于MDI的IDE,带有停靠的小部件,用于文件树,对象浏览器,编译器输出等等。但是有一件事情让我感到烦恼:我无法弄清楚如何以编程方式创建{{1小的。例如,此代码段创建了我的底部停靠窗口“构建信息”:

QDockWidget

启动时,我的程序看起来像这样(请记住开发的早期阶段):

Actual

但是,我希望它看起来像这样:

Expected

我似乎无法实现这一点。 QDockWidget上的Qt参考说明了这一点:

  

应在子窗口小部件中实现自定义大小提示,最小和最大大小和大小策略。 QDockWidget将尊重它们,调整自己的约束以包含框架和标题。不应在QDockWidget本身上设置大小约束,因为它们会根据是否停靠而改变

现在,这表明执行此操作的一种方法是子类m_compilerOutput = new QTextEdit; m_compilerOutput->setReadOnly(true); dock = new QDockWidget(tr("Build Information"), this); dock->setWidget(m_compilerOutput); addDockWidget(Qt::BottomDockWidgetArea, dock); 并覆盖QTextEdit方法。但是,我不想仅仅为了这个目的而这样做,我也没有尝试过它来找到一个有效的解决方案。

我尝试调用sizeHint(),使用每个选项调用dock->resize(m_compilerOutput->width(), m_compilerOutput->minimumHeight()) ...到目前为止,没有任何内容影响大小。就像我说的那样,我宁愿在几行代码中使用一个简单的解决方案来创建一个子类来改变m_compilerOutput->setSizePolicy()。所有建议都表示赞赏。

8 个答案:

答案 0 :(得分:7)

我放轻松了: HEADER:

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

来源:

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);
}

答案 1 :(得分:6)

考虑到它的子窗口小部件,听起来像停靠窗口小部件将自身重新调整为适当的大小。从QDockWidget文档(强调我的):

  

QDockWidget充当其子窗口小部件的包装器,使用setWidget()设置。应在子窗口小部件中实现自定义大小提示,最小和最大大小以及大小策略。 QDockWidget将尊重它们,调整自己的约束以包含框架和标题。不应该在QDockWidget本身上设置大小约束,因为它们会根据它停靠的方式而改变;停靠的QDockWidget没有框架和较小的标题栏。

为了更改大小,您必须重新调整子窗口小部件的大小。

编辑:Qt文档在讨论大小提示时有时会产生误导。通常,它指的是任何类型的调整大小,无论是由窗口小部件自动执行还是以编程方式执行。

答案 2 :(得分:4)

我刚刚完成了同样的过程。在Dock小部件及其包含的小部件上尝试了resize()adjustSize()和朋友的太多排列后,其中没有一个工作,我最终继承了QListView并添加了sizeHint()方法

现在它就像一个魅力。

答案 3 :(得分:2)

您是否尝试过停靠小部件内的resize()上的QTextEdit?您还可以尝试暂时设置停靠小部件的最大值和放大倍数。最小尺寸到您想要的尺寸,然后恢复原始值。

答案 4 :(得分:2)

你可以这样做:

设置QTextEdit的最大高度:

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

然后在主窗口的show event中将其设置为旧尺寸或高位:

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

这就是你应该需要的一切。

答案 5 :(得分:1)

使用QDockWidget::widget()上的调整大小(即QDockWidget正在管理的小部件)的测试不能始终按预期工作。

使用QDockWidget子类(DW),其中添加了QWidget QHBoxLayout,其中包含两个小部件(左侧面板和右侧面板) ,所有这些都将其大小策略设置为QSizePolicy::Minimum,DW通常都有两个面板小部件可见。当DW位于侧面扩展坞中时,处理DW QMainWindow信号的应用程序(dockLocationChanged)插槽会隐藏左侧面板,并将DW->widget()重新调整为右侧面板的大小。当DW以编程方式移动到底部停靠区域时,leftPanel设置为可见,DW填充主窗口的整个宽度(当然)。然后,当DW以编程方式移动到侧面停靠区域时,左侧面板将被隐藏,DW将重新调整大小。这按预期工作。但是,如果将DW从底部停靠区域拖动到侧面停靠区域,虽然隐藏了左侧面板并且像以前一样应用了重新调整大小,但DW不会像重新定位以编程方式一样重新调整大小。可以通过拖动DW和主窗口中心区域之间的分割器手动来手动重新调整DW的大小。请注意,主窗口中心区域为QWidget,其QHBoxLayout大小为QSizePolicy::Expanding

重新调整DW后调用主窗口上的adjustSize无效。尽管DW已重新实现sizeHint以返回其最小尺寸,具体取决于左侧面板是否可见。

要么我错过了如何控制QDockWidget的大小(考虑到我已经理解布局管理系统各部分之间的所有交互的困难,很可能),或者QMainWindow忽略或覆盖正在给出的布局指令。在QDockWidget重新定位操作期间仔细检查事件流建议后者:在插槽处理后,dockLocationChanged信号完成了其大小调整工作并返回到事件循环,我可以看到QMainWindow ,当用户重新定位完成后,对受影响的QDockWidget应用其他重新调整大小的操作,从而撤消尝试控制扩展坞大小的应用程序逻辑。 QMainWindow ....

似乎有些不对劲

答案 6 :(得分:1)

如果dockWidgets停靠,则其大小由其父级控制。在这种情况下,您可以使用QMainWindow::resizeDocks功能。

如果是浮动的,尺码由他们的孩子决定。调整儿童尺寸以达到您的目的。

答案 7 :(得分:0)

在MainWindow最大化时调整Dock小部件问题的大小在QTBUG-16252中进行了描述(https://bugreports.qt.io/browse/QTBUG-16252

我发现了另一种解决方法。适用于Windows 7的QT 5.4.1 minGW。 看起来一些窗口小部件状态恢复操作与QApplication事件循环密切相关。

只有在满足以下条件时才能正确恢复DockWidget大小:

  1. 在输入QApplication :: exec()之前调用restoreGeometry()(例如,在MainWindow类的构造函数中)

  2. restoreState()被称为AFTER exec()(例如通过QTimer)

  3. 这是我的代码:

    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);
    
    }