Название: Облегчение создания сложных виджетов с контейнерами в Qt Designer Отправлено: kdm от Апрель 03, 2011, 23:56 Если у вас сложный виджет вроде панели с заголовком (как во вложении), а ниже заголовка -контейнер для виджетов, которые в него надо добавлять в дизайнере и надо таких панелей много, то чтобы не писать все вручную (добавление виджетов в контейнер), а визуально все лицезреть и руками добавлять в контейнер виджеты, можно сделать небольшой хак.
Для таких целей правильнее сделать плагин для дизайнера и правильно все делать все тогда... но у нас нет времени или мы не знаем, как это делать, или и то и другое (как например, у меня (плюсуем "влом"). Тогда есть в дизайнере возможность преобразовать виджет к нужному типу (правой кнопка мыши по виджету и "преобразовать в", указываем имя класса и заголовочный файл, жмемь добавить, преобразовать). Надо отметить, что дизайнер будет генерировать код, который как бы работает с QWidget, но на самом деле использует в качестве имени класса тот, который мы указали. Поэтому с этим мы и поиграемся. Итак поместим объект QWidget на форму, преобразуем его в WidgetsGroup (который будет представлять из себя панель с заголовком и контейнером для кнопок, лейболов... чего угодно. Напишем этот класс (я сделал это, добавивь класс формы, как во вложении). Приведем код заголовочного файла класса. Код
И приведем файл реализации. Все в принципе обычно, как делает креатор по умолчанию. Код
Теперь будем думать. Для того, чтобы дизайнер, а если быть точнее UI Compiler сгенерировал код, который бы сам добавлял виджеты в контейнер Contents, то было бы очень просто, мы просто добавили метод setLayout в этот класс, с помощью которого бы потом все виджеты добавлись куда нужно. Но код генеруется примерно такой: Код То есть назначение лейаута идет в указании парента в конструкторе лейаута. Это немного все усложняет. Но только немного. При добавлении чайлда к потомкам QObject (коим является и этот класс) происходит событие childEvent. Переопределим метод класса, который обрабатывает это событие. Код Поместим туда определение название класса, который добавлеятся в качестве чайлда и, если он QObject, то наверняка это тот самый потомок QLayout, которого добавляет код формы к нашему классу вместе с виджетами чайлдами (кнопками, лейблами...). Если все-таки это виджет, то это те самые кнопки и лейблы. Код Здесь отметим, что если мы проведем реперант лейаута сразу: Код То наткнемся на сег. фолт, который будет происходит, когда что-то в мутексе пытается обратиться к полю d->recursive и т.д. (глубокая отладка ничего прояснить не дала по этому поводу) в одном из файлов Qt. Поэтому сразу репарент производить не следует, для этого воспользуемся сигнал-слотовым механизмом Qt, т.к. postEvent(Contents, child) тоже не дал нужных результатов. Добавим к классу сигнал wantAddLayout (QLayout* layout), который сигнализирует о том, что класс хочет добавить лейаут в свой виджет-контейнер Contents: Код И прайвет-слот, который будет принимать этот сигнал: Код Теперь свяжем в конструкторе сигнал со слотом, используя тип соединения QueuedConnection, что позволит отложить на время репарент, дав тем самым всему что генерировало сег. фолт "инициализировывывы...ваться". Код В обработчике события childEvent добавим следующие строки Код Теперь надо подумать о том, что не только тот код дизайнере захочет добавить лейаут к виджету, который мы будем использовать позже для дизайна главной формы, но еще и код, который располагает виджеты внутри этого класса по местам. Поэтому добавим флаг, означающий что эта форма построена и все последующие добавления чайлдов это уже из главной формы. Код Используем этот флаг в конструкторе: Код ... и в обработчике события: Код Таким образом все готово. Можно использовать этот класс для того, чтобы мутить много панелей в главной форме и в них располагать виджеты-кнопки, лейблы... (как показано во вложении) Код и исполняемый файл релиз-версии находится двумя постами ниже (из-за переполнения вложений для этого поста). Название: Re: Облегчение создания сложных виджетов с контейнерами в Qt Designer Отправлено: Fat-Zer от Апрель 04, 2011, 00:18 а можно выложить полный код, а то здесь буковок очень много читать их не хочется, а по коду посмотреть, что это, будет быстрее.
Название: Re: Облегчение создания сложных виджетов с контейнерами в Qt Designer Отправлено: kdm от Апрель 04, 2011, 00:22 Делал в проекте одном вырежу оттуда все ненужное и вложу в первый месседж код. Просто решил сделать запостить такую муть, а вот типа что вы думаете, потом подумал, что можно сделать пост для кладовой готовых решений.
Edit: Вложения в первом посте переполнились, поэтому выкладываю тут. Краткий очерк, зачем это делал: нужны были панельки с заголовками, в которых определенная функциональность и одновременно с этим нужно было легко размещать все элементы внутри них в дизайнере. Плагин для дизайнера писать не хотелось, никогда не пробовал, не знаю как делать, сколько времени уйдет, вот узнав, про то, что можно преобразовывать виджеты в дизайнере, решил сделать такой вот хак, чтобы и класс панельки сделать и виджеты внутрь нее запихнуть из дизайнера. Так вот, чтобы думаете по поводу такового вот подхода? Название: Re: Облегчение создания сложных виджетов с контейнерами в Qt Designer Отправлено: kdm от Апрель 04, 2011, 01:04 Есть готовые решения для панелек, например, Sintegrial Action Panel, однако в дизайнере, добавляемые в них добавляемые виджеты просто плавают, ни лейаут не задать, ни как-то упорядочить и так и появляются. А писать плагин к дизайнеру дело муторное, потому что для дизайнера можно и mingw собирать, а для модуля дизайнера в креаторе надо студией, либо пересобирать креатор, при чем возникали траблы сборки.
|