Поведение QDockWidget при изменении его содержимого
У меня проблема с одним из моих QDockWidget
, У меня есть несколько QWidget
предметы в QDockwidget
которые иногда видны, иногда нет.
Я хотел бы, чтобы мой QDockWidget
изменяет размер в зависимости от его содержания... Не только когда QWidgets
появляются в нем, но и когда они исчезают...
Пока мой QDockWidget
меняет себя, когда больше QWidgets
отображаются в нем, но когда я заставляю их исчезать, QDockWidget
остается в своем прежнем размере...
Есть идеи, чтобы помочь?
Заранее спасибо!
2 ответа
На протяжении многих лет были различные посты, касающиеся контроля размера QDockWidget
в QMainWindow
область дока. Я тоже боролся с этим вопросом и смог достичь лишь частичного и несколько неудовлетворительного решения. Основная проблема (если вы извините за каламбур) заключается в невозможности получить контроль над механизмом стыковки в контексте QMainWindow
это делает работу по управлению своими районами доков. Попытки использовать управление макетом - управление размерами и подсказки по размеру - не эффективны; QMainWindow
делает свое дело при изменении размеров области док-станции.
Во-первых, какой ограниченный успех у меня был:
Начиная с QMainWindow
подкласс (MW
) и QDockWidget
подкласс (DW
). DW
имеет QWidget
с QHBoxLayout
, то есть setWidget
в DW
, Этот макет имеет два виджета - я буду называть их панелями - с одной из этих панелей, предназначенных для отображения или скрытия в зависимости от контекста: отображается, когда DW
находится в нижней или верхней области дока или плавающий, скрытый в противном случае. sizeHint
другой панели после построения используется (вместе с соответствующим интервалом полей), чтобы установить "базовый размер" DW
с построенным sizeHint
ширина панели, которая изменит видимость, при необходимости увеличивая базовый размер: DW
реализация обеспечивается panel_visible
метод, который используется для включения или отключения панели переменных, применяя setVisible к панели и изменяя значение sizeHint
на величину приращения. Политика размера DW
и его панели установлены на минимум.
в MW
DW
dockLocationChanged
а также topLevelChanged
сигналы подключены к DW_resize
слот. Здесь, когда DW
isVisible
, isWindow
ложно и MW::dockWidgetArea
сообщает либо LeftDockWidgetArea
или же RightDockWidgeArea
, DW::panel_visible(false)
призван изменить эффективный DW
размер (когда вышеуказанные условия не выполняются DW::panel_visible(true)
называется, конечно). Вызов DW::resize
, а также updateGeometry
а также update
в MW
не влияет на размер области дока. Однако если DW::setMaximumSize(DW::sizeHint())
называется область дока правильно изменен (нет updateGeometry
или же update
требуется). Это работает по желанию, когда DW
перемещается (путем перетаскивания или двойного щелчка по его строке заголовка), а затем повторно блокируется (при двойном щелчке по его строке заголовка или перетаскиванием его назад через боковую область дока). Все идет нормально.
Теперь подвох:
Принуждение MW
подгонять свою область дока к предписанному DW
размер DW
должен быть освобожден от ограничения фиксированного размера, чтобы пользователь мог изменить размер области закрепления, перетаскивая ручку вертела, предоставленную MW
между дока и центральной зоной. Очевидный ответ - просто позвонить DW::setMaximumSize(0xFFFFFF, 0xFFFFFF)
"освободить" DW
ограничения. Да, за исключением того, что оптимизация рисования обновлений, которая происходит за кулисами, объединяет два события определения размера, в результате чего первоначальное действие сжатия док-станции теряется. Положив qApp->sendPostedEvents()
а также qApp->flush()
между двумя setMaxmimumSize
вызывает этот оптимизирующий эффект, область док-станции соответствует DW
размер, а затем оставляется освобожденным, так что область док-станции может быть изменена пользователем... иногда.
Это решение работает, когда DW
переходит из плавающего в закрепленный, дважды щелкнув DW
строка заголовка, но не когда DW
перетаскивается в боковой док в MW
, Так, например, если пользователь перетаскивает DW
от левой до правой доки правая область дока не изменяется, как ожидалось; площадь принимающего дока остается размером с плавающей DW
это производится во время перетаскивания с одной стороны на другую. Если DW
в области получающей док-станции дважды щелкните ее строку заголовка (чтобы снова стать плавающей), а затем снова дважды щелкните (чтобы вернуть ее в ту же область док-станции) MW
теперь соответствует области док-станции, как и предполагалось. При ближайшем рассмотрении - путем мониторинга MW::paintEvent
- Я вижу, что, когда площадь дока заканчивается желаемым размером, flush()
немедленно сопровождается paintEvent
где DW
отчеты, имеющие предполагаемый размер и после второго setMaximumSize
что не ограничивает DW
paintEvent
происходит с DW
все еще предполагаемый размер. Но когда DW
перетаскивается в область дока flush()
снова сразу сопровождается paintEvent
где DW
отчеты, имеющие предполагаемый размер, но после второго setMaximumSize
в этом случае есть два paintEvent
с DW
теперь удивительно, имея свой предыдущий плавающий размер!
Мне еще предстоит найти способ предотвратить это необъяснимое нарушение DW
размер после того, как он был правильно измерен. Кажется очевидным, что дополнительное событие изменения размера генерируется MW
после DW_resize
обработка слота вернулась из информации о размере, MW
удерживался до того, как были выпущены сигналы, ведущие к слоту. Мониторинг MW::eventFilter
действительно показывает событие Resize, происходящее после DW_resize
вернулся, что меняет DW
размер от того, что было установлено в коде слота, обратно к его размеру, когда он был плавающим. При двойном щелчке DW
панель плитки используется для перемещения DW
от плавания обратно в боковую док-станцию после события DW_resize
слот возвращается.
Таким образом, задача состоит в том, чтобы предотвратить неожиданное изменение размера после DW
был правильно измерен в DW_resize
слот. Возможно какое-то принуждение в DW::resizeEvent
избежит этой проблемы....
Лучше, конечно, было бы, если бы разработчики Qt предоставили разработчику приложений полный контроль над QMainWindow
API по своим действиям по управлению док-станцией - особенно по размеру док-зоны - и / или доступ к виджетам, которые он использует для управления док-зоной.
В настоящее время я использую Qt 4.6.2 в Linux, OS X и MS/Windows. Отчеты об отладке выше были сделаны в системе Intel OS X 10.6.7; результаты несколько различаются на разных платформах, но основная проблема одна и та же. Возможно эти QMainWindow
/QDockWidget
проблемы были рассмотрены в более поздней версии Qt? Возможно, кто-то глубже понимает, что здесь происходит, и может предложить простое решение?
У меня была такая же проблема. Необъяснимо выкладывать restoreState()
дважды решил это для меня.
Я использую Qt 4.7.0.
void MainWnd::showEvent(QShowEvent *se){
QMainWindow::showEvent(se);
static bool first = true;
if (first){
restoreState(...);
restoreState(...);
first = false;
}
}