Название: Выпадающие списки
Отправлено: tyorn от Август 11, 2015, 16:17
Добрый день. Пытаюсь реализовать выпадающие списки, элементы которого в свою очередь могут иметь подсписки (произвольное количество вложенности). Для этого написал простой класс, который позволяет хранить это дерево и в данный момент пытаюсь сделать qml часть, которая это дело отображала бы, однако столкнулся с проблемой рекурсии. Как ее решить? Вот собственно код. menu.h #include <QObject> #include <QList> #include <QString> #include <QVariant>
class Menu : public QObject { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) //Q_PROPERTY(QList<Menu* > subMenuItems READ subMenuItems NOTIFY subMenuItemsChanged) public: explicit Menu(QString text, QObject *parent = 0);
QString text() const; void setText(const QString& text);
void addItem(Menu* item);
int count() const;
signals: void textChanged(); void subMenuItemsChanged(); public slots: bool hasSubMenu() const; QList<Menu* > subMenuItems() const; QList<QVariant> subMenuItemsAsQVar() const;
private: QString m_text; QList<Menu *> m_subMenuItems; }; Q_DECLARE_METATYPE(Menu*) Q_DECLARE_METATYPE(QList<Menu*>)
#endif // MENU_H menu.cpp #include "menu.h" #include <QDebug>
Menu::Menu(QString text, QObject *parent) : QObject(parent), m_text(text) {
}
QString Menu::text() const { return m_text; }
void Menu::setText(const QString &text) { if (m_text != text) { m_text = text; emit textChanged(); } }
QList<Menu* > Menu::subMenuItems() const { return m_subMenuItems; }
int Menu::count() const { return m_subMenuItems.count(); }
bool Menu::hasSubMenu() const { return (!(m_subMenuItems.isEmpty())); }
void Menu::addItem(Menu *item) { m_subMenuItems<<item; }
QList<QVariant> Menu::subMenuItemsAsQVar() const { QList<QVariant> tl; for (int i = 0; i < count(); ++i) { tl<<QVariant::fromValue(m_subMenuItems[i]); //qDebug()<<tl[i]; } return tl; }
ClickableCMItem.qml import QtQuick 2.0 Item{ property alias label: labelText.text id: root Text { id: labelText text: modelData.text
MouseArea { anchors.fill: parent
onClicked: { popupSubMenuWrap.visible ^= true popupSubMenuWrap.x = parent.x popupSubMenuWrap.y = parent.y + parent.height } } }
Rectangle { id: popupSubMenuWrap width: 150 height: 400 visible: false PopupContent { model: modelData.subMenuItemsAsQVar() //model: menu.subMenuItems() } } main.qml import QtQuick 2.0
Rectangle { id: root width: 300 height: 600
ListView { id: rootList model: menu delegate: Component { id: rootListViewDelegate Item { width: root.width height: 25
Column { ClickableCMItem { label: menu.text } } } }
}
PopupContent.qml import QtQuick 2.0
ListView { anchors.fill: parent
delegate: Component { id: viewDelegat Item { width: root.width height: 25 Column { ClickableCMItem { label: modelData.text } //Text { // text: modelData.text //}
} } } } Вот собственно и все.
Название: Re: Выпадающие списки
Отправлено: ksk- от Август 11, 2015, 18:44
Что-то как-то мудрёно слишком, по-моему. В QML есть готовый компонент "Menu". Почему бы не воспользоваться им?
Название: Re: Выпадающие списки
Отправлено: Отражение луны от Август 12, 2015, 20:44
Что-то мудрено как-то (2) зачем хранить данные в каком-то там классе, если их можно хранить в яваскрипт массиве? И что за проблема с рекурсией? Нужны подробности на тему чего смотреть.
Название: Re: Выпадающие списки
Отправлено: tyorn от Август 13, 2015, 09:55
мудрёно потому что мне нужен кастомный стиль отображения, но использовать приходится qt 5.2.1 в котором нет MenuStyle QML Type, у Menu все еще есть свойство style, но явное задние стиля вроде style: someMyStyleComponent {} не отрабатывает на Mac'е, хотя вполне себе работает на Win. В итоге решил написать свой компонент. проблема рекурсии в том, что нельзя сделать компонент вида (примерно): @Popup.qml ListView { ... delegate: { Item { ... Text {...} Popup {...} ... } } }
т.е. запрещено recursiv instantiate, что в общем-то логично и правильно. вопрос был в том как эту штуку обойти, на данный момент я это обхожу с помощью динамического создания компонента внутри Item. примерно так: Component.onCompleted: { var component = Qt.createComponent("qrc:/ClickableCMItem.qml") var clickable = component.createObject(out, { "model": "modelData.subMenuItemsAsQVar()", "label": modelData.text }) где ClickableCMItem.qml хранит все, что мне необходимо от подэлемента меню, включая и компонент popup для уже своих подэлементов (если такие есть). не знаю, есть ли другой способ, но этот вполне работает
Название: Re: Выпадающие списки
Отправлено: Отражение луны от Август 13, 2015, 12:55
Вы нашли самый верный способ, поздравляю )
|