Dostęp do C++ QLists z QML
Jeśli mam listę rzeczy w C++, jak to zrobić w QML (w Qt5 / QtQuick 2)? Wygląda na to, że QML może zrozumieć tylko klasy pochodne QObject
, co jest problemem, ponieważ QObject
s nie można umieścić w QList
lub skopiować. Jak to zrobić:
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;
// ...
};
Żebym mógł zrobić coś takiego w QML:?
var a = thingManager.things[0].name;
9 answers
Natknąłem się na to pytanie, próbując rozwiązać podobny problem, w którym chciałem użyć kodu C++ jako źródła modelu w QML. Odpowiedź udzielona przez TheBootroo wskazała mi właściwy kierunek, ale nie zadziałała w pełni dla mnie. Nie mam wystarczającej reputacji, aby odpowiedzieć mu bezpośrednio (ale głosowałem na jego odpowiedź).
Używam Qt 5.0.0 Znalazłem ten link bardzo pomocny
Definicja ThingManager powinna zostać zmieniona w następujący sposób
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;
};
Zauważ, że zmieniłem zwraca typ getThings do listy QList
W kodzie QML, właściwości rzeczy mogą być dostępne poprzez model jako model.modelData.rozmiar i model.modelData.name.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-05 11:34:36
Alternatywnie, można użyć QVariantList
(QList<QVariant>
), po przekazaniu do QML automatycznie zmieni się na tablicę JavaScript i będzie można ją odczytywać i zapisywać z C++ i QML
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-14 16:20:44
Po więcej doświadczeń z QML znalazłem najlepszy sposób, aby mieć listy rzeczy jest z QAbstractListModel
.
Tworzysz Thing
z QObject
, więc może być przechowywany w QVariant
(Po zarejestrowaniu). Następnie możesz zwrócić rzeczywistą Thing
jako element modelu. Możesz uzyskać do niego dostęp w Repeater
jako model.display.a_property_of_thing
. Długość listy jest dostępna jako model.count
.
Ma to następujące zalety i wady:
- szybko - nie kopiuje całej listy, aby uzyskać dostęp do jednej element.
- możesz łatwo uzyskać animacje zmian na liście(dodawanie, przestawianie i usuwanie elementów).
- jest łatwy w użyciu z QML.
- aby animacje działały, za każdym razem, gdy zmieniasz listę, musisz wykonać nieco faffy bookkeeping (
beginInsertRows()
itp.)
...
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];
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-07 10:55:01
[[2]] Ah znalazłem odpowiedź (chyba nie sprawdzoną): QQmlListProperty
Jest kilka zastosowań w przykładach, np. w qtdeclarative/examples/quick/tutorials/gettingStartedQml/filedialog/directory.*
:
Niestety w tej chwili możesz mieć tylko listy tylko do odczytu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-11 23:39:09
Mylisz się co do QObject, mogą one być podane do QList, po prostu w formie wskaźnika, ponieważ następujące działania działają doskonale:
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;
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-29 08:48:44
Odpowiedź udzielona przez eatyourgreens
jest prawidłowa. Implementując w ten sposób swoją klasę, możesz uzyskać dostęp do tylu Potomków, ilu chcesz. Jeszcze jedna pomocna wskazówka, którą uznałem za przydatną, to utworzenie aliasu dla naszego modelu wewnątrz elementu delegata qml.
ListView {
anchors.fill: parent
model: thing_manager.things
delegate: ItemDelagate {}
clip: true
spacing: 10
}
A następnie w ItemDelegate.qml możesz utworzyć alias dla modelu, aby nie używać go przez cały czas.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
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-10 12:29:46
Best way use QQmlListProperty
.zobacz tę prostą próbkę, mam nadzieję, że ci pomogę.
obiekt i lista typów właściwości przykład
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-21 13:38:15
Jednym z bardzo pośrednich sposobów osiągnięcia tego jest:
I.) zrób model w qml
ListModel
{
id: thingModel
ListElement
{
size: 10
name: "Apple"
}
}
Ii.) następnie podaj kilka funkcji javascript, aby zmodyfikować tę listę np.
function jAppendThing( newSize, newName )
{
thingModel.append({"size": nameSize, "name": newName })
}
function jClearThing()
{
thingModel.clear()
}
Podobnie jDeleteThing itp..
Iii.) możesz przeczytać o Jak wywoływać funkcje qml z c++
Iv.) Uruchom pętlę na liście C++ i wywołaj funkcję dołączania qml, aby dodać wszystkie te dane do listy qml.
V.) przy każdej aktualizacji w C++, zmodyfikuj qml dane, jak również za pomocą powyższej funkcji, aby je aktualizować.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-11 23:14:34
Istnieje dobre, ale nie wymienione rozwiązanie:
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 MEMBER m_things NOTIFY thingssChanged)
// ...
private:
// ...
QList<Thing> m_things;
// ...
};
Odczyt i zapis mają zastosowanie. Brak kosztownego wywołania funkcji i kopiowania danych. Po prostu bezpośredni dostęp do członków klasy w QML:
var a = thingManager.things[0].name;
Aby uzyskać więcej informacji, zobacz doc: https://doc-snapshots.qt.io/qt5-dev/properties.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 10:52:02