На протяжении многих лет были различные посты, касающиеся контроля размера 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
a paintEvent
, происходит с DW
все еще предполагаемого размера. Но когда DW
перетаскивается в область стыковки, сразу за flush()
сразу же следует paintEvent
, где DW
сообщает о предполагаемом размере, но после второго setMaximumSize
в этом случае есть два paintEvent
s с DW
теперь удивительно имеет свой предыдущий плавающий размер!
Мне еще предстоит найти способ предотвратить необъяснимое переопределение размера DW
после правильного размера. Кажется очевидным, что дополнительное событие изменения размера генерируется MW
после того, как вернулась обработка слота DW_resize
, из информации о размере, из которой MW
держал до того, как были испущены сигналы, ведущие в слот. Мониторинг MW::eventFilter
действительно выявляет событие Resize, возникающее после возвращения DW_resize
, которое меняет размер DW
с того, который был установлен в коде слота, на его размер, когда он был плавающим. При двойном щелчке по плитке DW
для перемещения DW
из плавающего обратно в боковую док-станцию не происходит никакого дополнительного события Resize после возврата слота DW_resize
.
Задача состоит в том, чтобы предотвратить неожиданное изменение размера после того, как DW
был правильно определен в слоте DW_resize
. Возможно, какое-то принуждение в DW::resizeEvent
позволит избежать этой проблемы ....
Лучше, конечно, было бы, если бы разработчики Qt предоставили разработчику приложения полный контроль в API QMainWindow
над его действиями по управлению док-станцией - особенно размером области док-станции - и / или доступом к виджетам, которые он использует для док-станции. Управление территориями.
В настоящее время я использую Qt 4.6.2 в Linux, OS X и MS / Windows. Отчеты об отладке выше были сделаны в системе Intel OS X 10.6.7; результаты несколько различаются на разных платформах, но основная проблема одна и та же. Возможно, эти QMainWindow
/ QDockWidget
проблемы были рассмотрены в более поздней версии Qt? Возможно, кто-то глубже понимает, что здесь происходит, и может предложить простое решение?