C ++ cambiar el tamaño de un Qt QDockWidget acoplado mediante progtwigción?

Acabo de empezar a trabajar en un nuevo proyecto de C ++ / Qt. Será un IDE basado en MDI con widgets acoplados para cosas como el árbol de archivos, el navegador de objetos, la salida del comstackdor, etc. Sin embargo, una cosa me está molestando hasta ahora: no puedo imaginar cómo hacer que un QDockWidget más pequeño mediante progtwigción. Por ejemplo, este fragmento de código crea mi ventana de base inferior, “Información de comstackción”:

 m_compilerOutput = new QTextEdit; m_compilerOutput->setReadOnly(true); dock = new QDockWidget(tr("Build Information"), this); dock->setWidget(m_compilerOutput); addDockWidget(Qt::BottomDockWidgetArea, dock); 

Cuando se lanza, mi progtwig tiene este aspecto (teniendo en cuenta la etapa inicial de desarrollo):

Real

Sin embargo, quiero que aparezca así:

Esperado

Parece que no puedo conseguir que esto suceda. La referencia de Qt en QDockWidget dice esto:

Las sugerencias de tamaño personalizado, el tamaño mínimo y máximo y las políticas de tamaño deben implementarse en el widget secundario. QDockWidget los respetará, ajustando sus propias restricciones para incluir el marco y el título. Las restricciones de tamaño no deben establecerse en el QDockWidget, ya que cambian dependiendo de si está acoplado

Ahora, esto sugiere que un método para hacer esto sería sub-clase QTextEdit y anular el método sizeHint() . Sin embargo, preferiría no hacer esto solo para ese propósito, ni tampoco lo he intentado para encontrar que sea una solución operativa.

He intentado llamar a dock->resize(m_compilerOutput->width(), m_compilerOutput->minimumHeight()) , llamando a m_compilerOutput->setSizePolicy() con cada una de sus opciones … Hasta ahora, nada ha afectado el tamaño. Como dije, preferiría una solución simple en unas pocas líneas de código a tener que crear una subclase solo para cambiar sizeHint() . Todas las sugerencias son apreciadas.

Acabo de pasar por este mismo proceso. Después de probar demasiadas permutaciones de adjustSize() resize() , adjustSize() y friends en los widgets de dock y su widget contenido, ninguno de los cuales funcionó, terminé subclasificando QListView y agregando ese método sizeHint() .

Ahora funciona como un encanto!

Lo hice fácil: HEADER:

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

FUENTE:

 QSize oldMaxSize, oldMinSize; void MainWindow::setDockSize(QDockWidget* dock, int setWidth,int setHeight) { oldMaxSize=dock->maximumSize(); oldMinSize=dock->minimumSize(); if (setWidth>=0) if (dock->width()setMinimumWidth(setWidth); else dock->setMaximumWidth(setWidth); if (setHeight>=0) if (dock->height()setMinimumHeight(setHeight); else dock->setMaximumHeight(setHeight); QTimer::singleShot(1, this, SLOT(returnToOldMaxMinSizes())); } void MainWindow::returnToOldMaxMinSizes() { ui->dockWidget->setMinimumSize(oldMinSize); ui->dockWidget->setMaximumSize(oldMaxSize); } 

Suena como que el widget de base cambia de tamaño al tamaño adecuado, considerando su widget secundario. De la documentación de QDockWidget (énfasis mío):

Un QDockWidget actúa como un contenedor para su widget hijo, establecido con setWidget (). Las sugerencias de tamaño personalizado, el tamaño mínimo y máximo y las políticas de tamaño deben implementarse en el widget secundario . QDockWidget los respetará, ajustando sus propias restricciones para incluir el marco y el título. Las restricciones de tamaño no deben establecerse en el QDockWidget, ya que cambian dependiendo de si está acoplado; un QDockWidget acoplado no tiene marco y una barra de título más pequeña.

Para cambiar el tamaño, debe redimensionar el widget secundario.

EDITAR: la documentación de Qt a veces puede ser engañosa cuando se tratan sugerencias de tamaño. A menudo, se refiere a cualquier tipo de cambio de tamaño, ya sea realizado automáticamente por el widget o programáticamente.

Esta es una pregunta antigua, pero quería añadir que Qt 5.6 introdujo la función QMainWindow :: resizeDocks para manejar esto.

Desafortunadamente, no funciona para mi caso de uso (mover el separador entre dos QDockWidgets que se han dividido con QMainWindows :: splitDockWidget)

¿Ha intentado llamar a QTextEdit resize() en el QTextEdit dentro de su widget dock? También puede intentar configurar temporalmente los tamaños máximo y mínimo del widget de acoplamiento al tamaño que desea, y luego restaurar los valores originales.

Podrías hacer esto:

Establecer una altura máxima para su QTextEdit :

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

Y luego, en el evento show de tu ventana principal, vuelve a tener el tamaño anterior o algo alto:

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

Eso es todo lo que necesitas.

Las pruebas que usan el cambio de tamaño en el QDockWidget::widget() (es decir, el widget que el QDockWidget está administrando) no funcionan de manera consistente como se esperaba.

Con una subclase QDockWidget (DW) en la que se QWidget un QWidget con un QHBoxLayout que tiene dos widgets ( panel izquierdo y panel derecho ), todos los cuales tienen sus políticas de tamaño establecidas en QSizePolicy::Minimum , el DW normalmente tiene ambos paneles widgets visibles. Cuando el DW se coloca en un dock lateral, una ranura de aplicación ( QMainWindow ) que maneja la señal dockLocationChanged del DW oculta el panel izquierdo y DW->widget() el tamaño del DW->widget() al tamaño derecho del panel. Cuando el DW se mueve programáticamente al área inferior del muelle, el panel izquierdo se configura como visible y el DW llena todo el ancho de la ventana principal (por supuesto). Cuando el DW se mueve luego programáticamente a un área de acoplamiento lateral, el panel izquierdo se oculta y el DW se redimensiona hacia abajo. Esto funciona según lo previsto. Sin embargo, si el DW se arrastra desde el área de la base inferior al área de acoplamiento lateral, aunque el panel izquierdo está oculto y el tamaño se aplica como antes, el DW no se redimensiona como cuando el reposicionamiento se realiza mediante progtwigción. El DW se puede redimensionar manualmente arrastrando la manija del divisor entre el DW y el área central de la ventana principal. Tenga en cuenta que el área central de la ventana principal es un QWidget tiene un QHBoxLayout con políticas de tamaño QSizePolicy::Expanding .

La llamada a adjustSize en la ventana principal después de que el DW ha sido redimensionado no tiene ningún efecto. Esto a pesar de que el DW ha reimplementado sizeHint para devolver su tamaño mínimo dependiendo de si el panel izquierdo está visible o no.

O me falta algo sobre cómo controlar el tamaño de QDockWidget (lo cual, dada la dificultad que he tenido al entender todas las interacciones entre las partes del sistema de gestión de diseño, es muy probable), o QMainWindow ignora o QMainWindow el diseño Instrucciones que se le está dando. El examen QDockWidget la secuencia de eventos durante las operaciones de reposicionamiento de QDockWidget sugiere lo último: después de que la ranura de la señal dockLocationChanged haya realizado su trabajo de cambio de tamaño y haya regresado al bucle de eventos, puedo ver que QMainWindow , cuando se realiza el reposicionamiento del usuario, aplica un tamaño adicional Las operaciones en el QDockWidget afectado QDockWidget la lógica de la aplicación que intenta controlar el tamaño de la base. Algo parece estar mal en la QMainWindow ….

El problema de cambio de tamaño de los dispositivos de acoplamiento cuando MainWindow está maximizado se describe en QTBUG-16252 ( https://bugreports.qt.io/browse/QTBUG-16252 )

He encontrado otra solución en él. Funciona para mí en QT 5.4.1 minGW en Windows7. Parece que algunas operaciones de restauración de estado de widget están estrechamente relacionadas con el bucle de eventos QApplication.

Los tamaños de DockWidget se restauran correctamente SOLAMENTE cuando se cumplen las siguientes condiciones:

  1. restreGeometry () se llama ANTES de ingresar QApplication :: exec () (por ejemplo, en el constructor de su clase MainWindow)

  2. restreState () se llama DESPUÉS de exec () (por ejemplo, a través de QTimer)

Aquí está mi código:

 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(restreWidgetSettings())); nt->connect(nt, SIGNAL(timeout()), SLOT(deleteLater())); nt->start(); restreWidgetSettings(true); } void MainWindow::restreWidgetSettings(bool geometryOnly) { //... QByteArray geometry = getSettings(); restreGeometry(geometry); if(geometryOnly) return; //... //create dock widgets here restreState(mainWindowState); } 

Si los dockWidgets están acoplados, los tamaños son controlados por sus padres. En tales casos, puede usar la función QMainWindow::resizeDocks .

Si flotan, los tamaños están determinados por sus hijos. Cambiar el tamaño de los niños para lograr su propósito.