Пользовательский виджет дизайнера Qt: область прокрутки, содержащая пользовательскую вертикальную компоновку

Я хочу сделать что-то довольно простое: добавить пользовательский виджет в дизайнер Qt, который в основном будет прокруткой, содержащей пользовательский вертикальный макет (я добавил некоторый код в вертикальный макет, чтобы обрабатывать его объекты для моих проектов). Идея заключалась в том, чтобы представить вертикальное меню, которое было бы сбоку от моего экрана.

Что я уже сделал

Я создал собственный плагин виджета и свой собственный макет.

Мои пользовательские коды виджетов выглядят так:

#include "menuwidget.h"

MenuWidget::MenuWidget(QWidget *parent) :
        QScrollArea(parent)
{
    this->setWidgetResizable(true);
    QWidget* layoutHoldingWidget= new QWidget(this);
    layout= new MenuLayout();
    layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
    layout->addStretch(1);
    layoutHoldingWidget->setLayout(layout);
    this->setWidget(layoutHoldingWidget);
}

Если я добавлю вручную в макет (в код конструктора) некоторые кнопки

for(int i =0;i<20;i++)
    layout->addWidget(new QPushButton(this));

Это работает, и я вижу свою область прокрутки, содержащую несколько кнопок, что почти то, что я хочу.

Что я хочу

Я хотел бы иметь возможность добавлять эти кнопки непосредственно через дизайнер Qt: пользователь сначала перетаскивал бы пустой виджет MenuWidget в главное окно, а затем перетаскивал бы QPushButtons на мой пользовательский виджет точно так же, как он делал бы это в обычном вертикальном макете.

Возможно ли это? Как я мог сделать такое?

Спасибо ! :)

Изменить 1

Чего мне не хватало, так это виджета «scrollAreaWidgetContents», который всегда создается при перетаскивании QScrollArea. Я сделал то же самое, добавив виджет (назовем его containerWidget) в мою пользовательскую область прокрутки в ее функции domXml, которая позволяет мне перетаскивать виджеты в мою область прокрутки, как я хотел.

НО я все еще кое-что не могу понять: я хочу, чтобы у containerWidget был customLayout (myCustomLayout) . Если я добавлю его в функцию domXml, я получу в терминале следующую строку:

Дизайнер: тип макета «MyCustomLayout» не поддерживается, по умолчанию используется сетка.

Так что это означает, что я не могу сказать дизайнеру использовать мой пользовательский макет для размещения моих виджетов, что довольно печально: D

Есть ли здесь способ «обмануть»?


person psykhi    schedule 12.08.2013    source источник
comment
Прочтите о пользовательских виджетах в QtDesigner qt-project.org/ doc/qt-4.8/designer-using-custom-widgets.html   -  person Sebastian Lange    schedule 12.08.2013
comment
Я читал об этом, и я не понимаю, как это могло бы мне помочь. Мой вопрос довольно конкретный, я думаю.   -  person psykhi    schedule 12.08.2013
comment
Данная ссылка и связанная с ней документация объясняют, как расширить конструктор qt собственными виджетами и плагинами для виджетов.   -  person Sebastian Lange    schedule 12.08.2013
comment
Спасибо, но я читал этот документ бесчисленное количество раз. Мне нужна помощь по этой конкретной проблеме...   -  person psykhi    schedule 13.08.2013
comment
Я использую данную опцию для подкласса виджета и использую qt- project.org/doc/qt-4.8/designer-creating-custom-widgets.html или qt-project.org/doc/qt-4.8/qtdesigner.html руководство по созданию плагинов для QtDesigner. Все шаги должны быть упомянуты там. Судя по вашему описанию вы еще не создали полноценный плагин а просто замену. Следующим вашим шагом будет повторная реализация данных виртуальных функций, упомянутых в руководстве. Насколько я могу судить, там описано почти все, так что прочитайте эти ссылки в другой раз.   -  person Sebastian Lange    schedule 13.08.2013
comment
Как я писал в вопросе, я создал плагин QDesignerCustomWidgetInterface для своего виджета. Я вижу это в Qt Designer и перетаскиваю. Мне нужно было бы некоторое руководство о следующих шагах, чтобы следовать, чтобы достичь того, что я хотел бы сделать. Ответ, скорее всего, можно найти в документах, которые я прочитал, но я как бы застрял здесь со своей проблемой. Вот почему я пришел к stackoverflow... Итак, мой вопрос: как я могу управлять виджетами, которые я перетаскиваю в свои пользовательские виджеты с помощью Qt Designer?   -  person psykhi    schedule 13.08.2013
comment
Извините за недопонимание. Если ваш виджет правильно обрабатывает все в коде, он также должен работать в qtdesigner, если реализованы необходимые виртуальные методы. Ваш виджет вообще упорядочивает дочерний виджет? Может быть, ваши перетаскиваемые виджеты не размещаются на макете только на виджете?   -  person Sebastian Lange    schedule 14.08.2013
comment
Спасибо за ваш ответ, я отредактировал свой вопрос сейчас. Мне не хватало виджета контейнера области прокрутки. Но я пока не могу найти способ применить собственный макет к этому виджету-контейнеру:/   -  person psykhi    schedule 14.08.2013
comment
В конце концов вам также нужно будет создать плагин для вашего пользовательского макета. Хотя никогда этим не пользовался.   -  person Sebastian Lange    schedule 14.08.2013
comment
Да, и, похоже, это не поддерживается в Qt 4... qt-project.org /forums/viewthread/6322 Спасибо за помощь! :)   -  person psykhi    schedule 14.08.2013
comment
+1: Интересный вопрос. Наконец-то я нашел время протестировать интерфейс разработанного плагина :-) Я думаю, недостающим моментом было то, что макет должен обрабатываться не в QDesignerCustomWidgetInterface, а в вашем виджете с использованием QObject::childEvent, который также вызывается, когда виджет редактируется в QtDesigner.   -  person Valentin Heinitz    schedule 14.08.2013


Ответы (2)


Есть две вещи, которые следует учитывать:

1) Перезапишите в классе, полученном от QDesignerCustomWidgetInterface, функцию, чтобы она возвращала true

bool isContainer() const { return true; }

Это сообщает QtDesigner, что виджет может содержать дочерние элементы. (В Qt почти любой виджет может содержать любой виджет в качестве дочернего, но QtDesigner пытается ограничить его разумным образом - например, вы не можете добавлять дочерние элементы в QLabel в QtDesigner)

2) Реализуйте childEvent вашего виджета. Вероятно, в вашем случае это добавит в макет виджеты, добавленные в QtDesigner.

Вот ядро, которое я реализовал, чтобы попробовать это. Я создал скелет с помощью мастера «Qt Widget Plugin» в QtCreator и немного изменил его.

Не забудьте собрать как выпуск для компилятора/Qt-версии вашего QtDesigner, скопировать файлы .dll и .lib в каталог \plugins\designer и перезапустить. сильный> QtDesigner!

verticalplugin.cpp

//all other functions remained as created by QtCreator wizard
bool VerticalMenuPlugin::isContainer() const
{
    return true;
}

VerticalMenu.h

#ifndef VERTICALMENU_H
#define VERTICALMENU_H

#include <QtGui/QWidget>
#include <QtGui/QVBoxLayout>

class VerticalMenu : public QWidget
{
    Q_OBJECT

protected:
    virtual void childEvent ( QChildEvent * event );
public:
    VerticalMenu(QWidget *parent = 0);
};

#endif

VerticalMenu.cpp

#include "verticalmenu.h"
#include <QChildEvent>

VerticalMenu::VerticalMenu(QWidget *parent) :
    QWidget(parent)
{
    setLayout (new QVBoxLayout);
}

void VerticalMenu::childEvent ( QChildEvent * event )
{
    if ( event->added() )
    {
        QWidget * newChild = qobject_cast<QWidget *>(event->child());
        if ( newChild )
        {
            layout()->addWidget( newChild );
        }
    }
}

Я надеюсь, что это поможет в качестве отправной точки.

person Valentin Heinitz    schedule 14.08.2013
comment
Спасибо за этот ответ! Я обязательно попробую этот способ с методом childEvent, мне кажется, это очень хороший подход к моей проблеме :) - person psykhi; 14.08.2013

Qt 4 не поддерживает подключаемые модули пользовательского макета для дизайнера, поэтому я не смог добиться того, что хотел. хотел сделать. Вместо этого я буду использовать вертикальный макет и попытаюсь реализовать дополнительные функции, которые должны были быть в пользовательском коде макета, в коде виджета.

person psykhi    schedule 14.08.2013
comment
О, я опоздал на 12 минут :-( - person Valentin Heinitz; 14.08.2013
comment
+1: Спасибо за ссылку! Однако это можно решить и так, как я предложил. В конце концов, почему это должен быть макет? Qt Designer создает полностью рабочий виджет (если не указано иное в createWidget), который ведет себя так же, как виджет во время выполнения. Этот виджет может управлять своим содержимым, когда вы указываете дочерние элементы макета, сами создаете новые дочерние элементы, перемещаетесь по графическому интерфейсу Qt Designer и т. д.). Я предполагаю, что разработчик на форуме qt-project был слишком сосредоточен на настройке QLayout, а не на решении своей проблемы. (Никому не нужен бур, но отверстие) - person Valentin Heinitz; 14.08.2013