На картинке показан виджет для которого мы будем делать плагин, вот примерный код констурктора такого виджета:
PanelWithButtons::PanelWithButtons(QWidget *parent) :
QWidget(parent) { QVBoxLayout *layout = new QVBoxLayout(); QFrame *frame = new QFrame(this); frame->setObjectName(QLatin1String("InternalFrame")); frame->setFrameShape(QFrame::Box); layout->addWidget(frame, 1); QHBoxLayout *buttonsLayout = new QHBoxLayout(); buttonsLayout->addWidget(new QPushButton(tr("OK"), this)); buttonsLayout->addWidget(new QPushButton(tr("Cancel"), this)); layout->addLayout(buttonsLayout); setLayout(layout); }Все предельно просто, а на картинке справа, то, как наш виджет будет выглядеть в Object Inspector'е.
Для того, чтобы получить такой эффект, нам необходимо внести внутренний QFrame под наблюдение Qt Designer'а, для этого потребуется:
- Получить инстанс QDesignerFormWindowManagerInterface, это делается в методе initialize плагина, таким образом:
void PanelWithButtonsPlugin::initialize(QDesignerFormEditorInterface *core) { if (m_initialized) return; m_manager = core->formWindowManager(); Q_ASSERT(m_manager); m_initialized = true; }
Q_ASSERT нужен только для пущей уверенности при разработке. - Теперь в методе createWidget мы будем регистрировать наш фрейм:
QWidget *PanelWithButtonsPlugin::createWidget(QWidget *parent) { PanelWithButtons *panel = new PanelWithButtons(parent); QDesignerFormWindowInterface *window = m_manager->activeFormWindow(); if (window && parent == window->mainContainer()) { QFrame *frame = panel->findChild<QFrame *>(); Q_ASSERT(frame); window->manageWidget(frame); } return panel; }
Главная тонкость кроется в условии, дело в том, что метод createWidget вызывается в трех случаях:
1. Когда запускается Qt Designer.
2. Когда мышка начинает тащить виджет с панели на форму.
3. И когда виджет, наконец-то, размещается на форме.
Так вот, регистрировать внутренний виджет нужно только в третьем случае, иначе это приведет к крашу дизайнера. Первая часть условия в коде выше отбрасывает первый случай, если window пуст, значит речь идет о первичном запуске. Вторая часть условия обрабатывает второй случай, и значит буквально следующее: "если существует активное окно и это окно является родителем для нашего только что созданного виджета". Во втором случае виджет создается лишь для того, чтобы отображаться рядом с курсором, пока вы его тащите на форму, и этот инстанс будет уничтожен сразу же, как только виджет окажется на форме, следовательно для него нет необходимости вносить внутренний фрейм под наблюдение. - Для того, чтобы все это заработало, необходимо добавить следующие заголовки:
#include <QDesignerFormEditorInterface> #include <QDesignerFormWindowManagerInterface> #include <QDesignerFormWindowInterface>
Все равно не понимаю. Зачем это может понадобиться ?
ReplyDeleteДля того чтобы в ваш кастомный виджет можно было вставлять други виджеты прямо в дизайнере,а не толкьо посредством C++ кода.
DeleteЗдравствуйте. Встала такая же задача, основываясь на вашей статье попытался решить её, но безрезультатно. Дизайнер просто добавляет виджет на мой компонент, но не интегрирует его в определенную область. Не могли бы вы опубликовать исходники этого проекта, хочу свериться. Спасибо.
ReplyDeleteДоброго дня, проект для которого я это делал под NDA, а демка для этой статьи давно стерта с диска. Но, как говориться, I'm pretty sure что все необходимое здесь перечисленно. Вовсяком случае для 4 версии, хотя я сомневаюсь, что в 5 что-то сильно поменялось.
DeleteИ про интеграцию, я наеюсь что вы нt забываете в Object Inspector выставить нужный вам Layout?