C ++ изменяет размер пристыкованного Qt QDockWidget программно? - PullRequest
26 голосов
/ 27 апреля 2010

Я только начал работать над новым проектом C ++ / Qt. Это будет основанная на MDI IDE с закрепленными виджетами для таких вещей, как дерево файлов, браузер объектов, вывод компилятора и т. Д. Пока что меня беспокоит одна вещь: я не могу понять, как программно сделать QDockWidget меньше. Например, этот фрагмент создает мое нижнее окно дока «Информация о сборке»:

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

При запуске моя программа выглядит следующим образом (имейте в виду, на ранней стадии разработки):

Actual

Однако я хочу, чтобы это выглядело так:

Expected

Кажется, я не могу этого добиться. Справочник Qt по QDockWidget гласит:

Настраиваемые размеры подсказок, минимальные и максимальные размеры и политики размеров должны быть реализованы в дочернем виджете. QDockWidget будет уважать их, корректируя свои собственные ограничения, чтобы включить фрейм и заголовок. Ограничения размера не должны быть установлены на самом QDockWidget, потому что они изменяются в зависимости от того, закреплен ли он

Теперь, это говорит о том, что одним из способов сделать это было бы использование подкласса QTextEdit и переопределение метода sizeHint(). Тем не менее, я бы предпочел не делать это только для этой цели, и я не пытался найти это как рабочее решение.

Я пытался дозвониться до dock->resize(m_compilerOutput->width(), m_compilerOutput->minimumHeight()), вызывая m_compilerOutput->setSizePolicy() с каждой из его опций ... Ничто до сих пор не влияло на размер. Как я уже сказал, я бы предпочел простое решение в несколько строк кода, а не создание подкласса просто для изменения sizeHint(). Все предложения приветствуются.

Ответы [ 9 ]

7 голосов
/ 25 марта 2012

Я сделал это легко: ЗАГОЛОВОК:

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);
}
6 голосов
/ 05 мая 2010

Звучит так, будто виджет-док изменяет свой размер до нужного размера, учитывая его дочерний виджет.Из документации QDockWidget (выделено мной):

QDockWidget действует как оболочка для своего дочернего виджета, устанавливается с помощью setWidget ().Настраиваемые подсказки размеров, минимальные и максимальные размеры и политики должны быть реализованы в дочернем виджете .QDockWidget будет уважать их, корректируя свои собственные ограничения, чтобы включить фрейм и заголовок.Ограничения размера не должны быть установлены на самом QDockWidget, потому что они изменяются в зависимости от того, присоединен ли он к док-станции;закрепленный QDockWidget не имеет рамки и меньшей строки заголовка.

Чтобы изменить размер, необходимо изменить размер дочернего виджета.

РЕДАКТИРОВАТЬ: документация Qtиногда может вводить в заблуждение, когда речь идет о подсказках размера.Часто это относится к любому виду изменения размера, выполняется ли оно автоматически виджетом или программно.

5 голосов
/ 24 февраля 2017

Это старый вопрос, но я хотел бы упомянуть, что Qt 5.6 ввел функцию QMainWindow :: resizeDocks , чтобы справиться с этим.

К сожалению, это не работает для моего варианта использования (перемещение разделителя между двумя QDockWidget, которые были разделены с помощью QMainWindows :: splitDockWidget)

4 голосов
/ 22 мая 2013

Я только что прошел этот же процесс. Попробовав слишком много перестановок resize(), adjustSize() и друзей на виджетах док-станции и содержащихся в них виджетах, ни один из которых не сработал, я в итоге создал подкласс QListView и добавил метод sizeHint().

Теперь это работает как шарм.

2 голосов
/ 23 мая 2013

Вы можете сделать это:

Установите максимальную высоту для вашего QTextEdit:

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

А затем в событии показа вашего главного окна установите его обратно в старый размер или что-то высокое:

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

Это все, что вам нужно.

2 голосов
/ 02 мая 2010

Вы пытались позвонить resize() на QTextEdit внутри вашего виджета дока? Вы можете также попытаться временно установить максимальный и минимальный размеры виджета до того размера, который вам нужен, а затем восстановить исходные значения.

1 голос
/ 28 апреля 2017

Если dockWidgets закреплены, размеры контролируются их родителем. В таких случаях вы можете использовать функцию QMainWindow::resizeDocks.

Если плавающие, размеры определяются их детьми. Изменение размера детей для достижения вашей цели.

1 голос
/ 13 мая 2011

Тесты с использованием изменения размера на QDockWidget::widget() (т.е. виджет, которым управляет QDockWidget) не всегда работают должным образом.

С добавлением QDockWidget подкласса (DW), в который добавлен QWidget с QHBoxLayout, который имеет два виджета ( левая панель и правая панель ), каждый из которых имеет свои политики размера установлены на QSizePolicy::Minimum, в DW обычно видны оба виджета панели. Когда DW расположен в боковой док-станции, слот приложения (QMainWindow), обрабатывающий сигнал DWS dockLocationChanged, скрывает левую панель и изменяет размеры DW->widget() до размера правой панели. Когда DW программно перемещается в нижнюю область дока, leftPanel устанавливается видимым, и DW заполняет всю ширину главного окна (конечно). Когда DW затем программно перемещается в боковую область дока, левая панель скрывается, а DW изменяет размеры вниз. Это работает как задумано. Однако, если DW перетаскивается из нижней области дока в боковую область дока, хотя левая панель скрыта, а изменение размера применено, как и раньше, размер DW не уменьшается, как при перепрограммировании. Размер DW можно вручную уменьшить, перетаскивая ручку сплиттера между DW и центральной областью главного окна. Обратите внимание, что центральная область главного окна - QWidget, имеющая QHBoxLayout с размерами политик QSizePolicy::Expanding.

Вызов adjustSize в главном окне после изменения размера DW не имеет никакого эффекта. Это несмотря на то, что DW переопределил sizeHint, чтобы вернуть его минимальный размер в зависимости от того, видна ли левая панель или нет.

Либо я что-то упускаю в том, как контролировать размер QDockWidget (что, учитывая трудности, с которыми я столкнулся с пониманием всех взаимодействий между частями системы управления компоновкой, вполне вероятно), либо QMainWindow игнорирует или игнорирует инструкции макета, которые ему дают. Тщательное изучение потока событий во время операций репозиции QDockWidget позволяет предположить следующее: после обработки слота сигнал dockLocationChanged выполнил свою работу по изменению размера и вернулся в цикл обработки событий. Я вижу, что QMainWindow, когда репозиционирование пользователя выполнено , применяет дополнительные операции изменения размера к уязвимому QDockWidget, тем самым отменяя логику приложения, которая пытается контролировать размер дока. Что-то не так в QMainWindow ....

0 голосов
/ 15 мая 2015

Проблема изменения размера док-виджетов, когда MainWindow развернута, описана в QTBUG-16252 (https://bugreports.qt.io/browse/QTBUG-16252)

Я нашел другой обходной путь. У меня работает на QT 5.4.1 minGW на Windows7. Похоже, что некоторые операции восстановления состояния виджета тесно связаны с циклом событий QApplication.

Размеры DockWidget корректно восстанавливаются ТОЛЬКО при соблюдении следующих условий:

  1. restoreGeometry () вызывается ДО ввода QApplication :: exec () (например, в конструкторе вашего класса MainWindow)

  2. restoreState () называется ПОСЛЕ exec () (например, через QTimer)

Вот мой код:

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

}
...