Подтвердить что ты не робот

С++ изменяет размер загруженного Qt QDockWidget программно?

Я только начал работать над новым проектом С++/Qt. Это будет IDE на основе MDI с прикрепленными виджетами для таких вещей, как дерево файлов, браузер объектов, выход компилятора и т.д. Одну вещь прослушивает меня до сих пор: я не могу понять, как программно сделать 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(). Все предложения приветствуются.

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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

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

EDIT: Документация Qt иногда может вводить в заблуждение, когда обсуждаются подсказки о размерах. Часто это относится к любому типу изменения размера, независимо от того, выполняется ли оно виджет или программно.

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

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

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

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

Ответ 7

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

Задайте максимальную высоту для QTextEdit:

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

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

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

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

Ответ 8

Изменение размера виджетов виджета при максимальном использовании MainWindow описано в QTBUG-16252 (https://bugreports.qt.io/browse/QTBUG-16252)

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

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

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

  • restoreState() называется AFTER 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);

}

Ответ 9

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

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