Доступ к C ++ QLists из QML

Если у меня есть список вещей в C ++, как я могу представить это QML (в Qt5 / QtQuick 2)? Кажется, что QML может понять только QObjectклассы, что является проблемой, потому что QObjectне может быть помещен в QList или скопированы. Как мне это сделать:

struct Thing
{
int size;
QString name;
};

class ThingManager : public QObject
{
Q_OBJECT

// These macros support QtQuick, in case we one day want to use it to make a slick
// interface (when QML desktop components are released).
Q_PROPERTY(QList<Thing> things READ things NOTIFY thingssChanged)

public:
// ...
QList<Thing> things() const;

// ...

};

Чтобы я мог сделать что-то подобное в QML 😕

var a = thingManager.things[0].name;

24

Решение

Я столкнулся с этим вопросом, пытаясь решить аналогичную проблему, где я хотел использовать код C ++ в качестве исходного кода модели в QML. Ответ, данный TheBootroo, указал мне верное направление, но не сработал для меня полностью. У меня нет достаточной репутации, чтобы ответить ему напрямую (но я действительно одобряю его ответ).

Я использую Qt 5.0.0
я нашел эта ссылка очень полезно

Определение ThingManager должно быть изменено следующим образом

class ThingManager : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<QObject*> things READ getThings NOTIFY thingsChanged)

public:
QList<QObject*> getThings () const { return m_things; }

signals:
void thingsChanged ();

private:
QList<QObject*> m_things;
};

Обратите внимание, что я изменил тип возвращаемого значения getThings на QList<QObject *>, Без этого изменения Qt предупреждает, что он «не может обработать незарегистрированный тип данных» QList<Вещь*>«».

В коде QML к свойствам Thing можно получить доступ через модель как model.modelData.size и model.modelData.name.

21

Другие решения

В качестве альтернативы, вы можете использовать QVariantList (QList<QVariant>), он автоматически изменится на массив JavaScript при передаче в QML и будет доступен для чтения и записи из C ++ и QML

20

После большего опыта работы с QML я нашел лучший способ получить списки вещей с QAbstractListModel.

Вы делаете свой Thing вытекают из QObject так что он может быть сохранен в QVariant (после регистрации). Тогда вы можете вернуть фактический Thing в качестве элемента модели. Вы можете получить к нему доступ в Repeater как model.display.a_property_of_thing, Длина списка доступна как model.count,

Это имеет следующие плюсы и минусы:

  1. Быстрый — он не копирует весь список для доступа к одному элементу.
  2. Вы можете легко получить анимацию для внесения изменений в список (добавление, перестановка и удаление элементов).
  3. Это легко использовать из QML.
  4. Чтобы анимации работали, каждый раз, когда вы изменяете список, вам нужно сделать слегка прихотливую бухгалтерию (beginInsertRows() так далее.)

class Things : public QObject
{
...
};

Q_DECLARE_METATYPE(Thing*)

class ThingList : public QAbstractListModel
{
Q_OBJECT

public:
explicit ThingList(QObject *parent = 0);
~ThingList();

int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;

public slots:

// Extra function to get the thing easily from outside Repeaters.
Thing* thing(int idx);

private:
QList<Thing*> mThings;
};

int ThingList::rowCount(const QModelIndex& parent) const
{
return mThings.size();
}

QVariant ThingList::data(const QModelIndex& index, int role) const
{
int i = index.row();
if (i < 0 || i >= mPorts.size())
return QVariant(QVariant::Invalid);

return QVariant::fromValue(mThings[i]);
}

Thing* ThingList::thing(int idx)
{
if (idx < 0 || idx >= mThings.size())
return nullptr;

return mThings[idx];
}
8

Ах, я нашел ответ (я думаю, не проверено): QQmlListProperty

В примерах есть несколько применений, например в qtdeclarative/examples/quick/tutorials/gettingStartedQml/filedialog/directory.*:

К сожалению, на данный момент вы можете иметь только списки только для чтения.

4

вы совершенно не правы в отношении QObject, они могут быть переданы в QList, просто в виде указателя, так как следующее прекрасно работает:

class Thing : public QObject
{
Q_OBJECT

Q_PROPERTY (int     size READ getSize CONSTANT)
Q_PROPERTY (QString name READ getName CONSTANT)

public:
Thing(QObject * parent = NULL) : QObject(parent) {}

int     getSize () const { return m_size; }
QString getName () const { return m_name; }

private:
int     m_size;
QString m_name;
};

class ThingManager : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<Thing*> things READ getThings NOTIFY thingsChanged)

public:
QList<Thing*> getThings () const { return m_things; }

signals:
void thingsChanged ();

private:
QList<Things*> m_things;
};
2

Ответ, данный eatyourgreens верно. Реализуя свой класс таким образом, вы можете получить доступ к любому количеству потомков, сколько захотите. Еще один полезный совет, который я нашел полезным, — создать псевдоним для нашей модели внутри элемента делегата qml.

ListView {
anchors.fill: parent
model: thing_manager.things
delegate: ItemDelagate {}
clip: true
spacing: 10
}

И затем в ItemDelegate.qml вы можете создать псевдоним для модели, чтобы она не использовала все время model.modelData

Item{
width: 600
height: 200
property var thing: model.modelData
Rectangle {
anchors.fill: parent
color: "red"Text {
text: thing.name // or any other field
}
}
}
1

лучший способ использования QQmlListProperty
.посмотрите этот простой пример, я надеюсь, вам поможет.

Пример типов объектов и списков

1

Один из весьма косвенных способов достижения этого заключается в следующем:

я.) Сделать модель в qml

ListModel
{
id: thingModel

ListElement
{
size: 10
name: "Apple"}
}

ii.) Затем предоставьте пару функций javascript для изменения этого списка, например.

function jAppendThing( newSize, newName )
{
thingModel.append({"size": nameSize, "name": newName })
}

function jClearThing()
{
thingModel.clear()
}

аналогично jDeleteThing и т. д.

III.) Вы можете прочитать о как вызвать функции qml из c ++

iv.) Запустите цикл в вашем списке C ++ и вызовите функцию добавления qml, чтобы добавить все эти данные в список qml.

v.) При любом обновлении в боковом списке C ++ также измените данные qml, используя вышеуказанную функцию, чтобы они обновлялись.

0
По вопросам рекламы [email protected]