Question

I'm trying to use a QDeclarativeListProperty in order to manage a list of parameters, mostly for the purposes of displaying them in a ListView. However, I would also like to be able to directly access the parameters in QML from the QDeclarativeListProperty so that I can display/modify individual parameters on different screens.

My class is called ParameterClass, for which I've created a QList:

class SystemData : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QDeclarativeListProperty<ParameterClass> parameters READ parameters CONSTANT)
    QDeclarativeListProperty<ParameterClass> parameters();

...

    QList<ParameterClass *> m_parameterList;
}

I've also registered the ParameterClass class and set up an instance of my SystemData as a property, which I know is necessary.

m_context->setContextProperty("SystemData", m_pSystemData);
qmlRegisterType<ParameterClass>();

Now, what I want to do within QML is something like this:

Rectangle {
    id: frame
    property variant parameter: SystemData.parameters[5]
    ...
}

I'm just not getting it to work: I keep getting back [undefined]. Am I wasting my time, or am I missing something?

Edit: I've changed things to use the suggestion from ... . Here are some selections from my updated code.

main.cpp:

#include <QApplication>
#include <QSplashScreen>
#include <QLocale>
#include <QLibraryInfo>
#include <QDeclarativeView>
#include <QDeclarativeContext>
#include <QDeclarativeEngine>
#include <QObject>
#include <QDeclarativeListProperty>

#include "systemdata.h"
#include "parameterclass.h"

static const QString contentPath = "qrc:/qml/qml/pk_ui/";
static const QString filename(contentPath + "main.qml");

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QDeclarativeView mainView;
    SystemData* systemData = SystemData::getInstance();

    QThread thread;
    UpdateWorker updateWorker;
    QObject::connect((const QObject*)systemData, SIGNAL(startWork()),
                     (const QObject*)&updateWorker, SLOT(doWork()));
    updateWorker.moveToThread(&thread);
    thread.start();
    systemData->startUpdates();

    QFont defaultFont;
    defaultFont.setFamily("Sans Serif");
    QApplication::setFont(defaultFont);

    // Register types to be available in QML
    qmlRegisterType<ParameterClass>();
    qmlRegisterUncreatableType<SystemEnum>("SystemEnums", 1, 0, "SystemEnum", QString());

    mainView.engine()->rootContext()->setContextProperty("SystemData", systemData);

    // Set view optimizations not already done for QDeclarativeView
    mainView.setResizeMode(QDeclarativeView::SizeRootObjectToView);
    mainView.setAttribute(Qt::WA_OpaquePaintEvent);
    mainView.setAttribute(Qt::WA_NoSystemBackground);

    mainView.setSource(QUrl(filename));
    mainView.show();

    return app.exec();
}

The ParameterClass looks like this:

class ParameterClass : public QObject
{
    Q_OBJECT

    Q_PROPERTY(int type READ get_type NOTIFY typeChanged)
    Q_PROPERTY(bool enabled READ get_ParameterEnabled WRITE set_ParameterEnabled NOTIFY enabledChanged)
    Q_PROPERTY(int groupID READ get_GroupID WRITE set_GroupID NOTIFY groupIDChanged)
    Q_PROPERTY(int unitID READ get_UnitID WRITE set_UnitID NOTIFY unitIDChanged)
    Q_PROPERTY(int securityLevel READ get_SecurityLevel WRITE set_SecurityLevel NOTIFY securityLevelChanged)
    Q_PROPERTY(QString parameterName READ get_ParameterName NOTIFY parameterNameChanged)
    Q_PROPERTY(QString shortDescription READ get_ShortDescription NOTIFY shortDescriptionChanged)
    Q_PROPERTY(int currentValue READ get_CV WRITE set_valueptrvalue NOTIFY currentValueChanged)
    Q_PROPERTY(int lowerBound READ get_LB NOTIFY lowerBoundChanged)
    Q_PROPERTY(int upperBound READ get_UB NOTIFY upperBoundChanged)

public:
    struct ValueTypes
    {
        enum
        {
            IntegerType,
            StringType,
            StringListType
        };
    };


    ParameterClass(QObject *parent = 0);
    int get_type();
    bool get_ParameterEnabled();
    int get_GroupID();
    int get_UnitID();
    int get_SecurityLevel();
    QString get_ParameterName();
    QString get_ShortDescription();
    int get_CV() { return *CurrentValuePtr; }
    int get_LB() { return *LowerBoundPtr; }
    int get_UB() { return *UpperBoundPtr; }

    void set_ParameterEnabled(bool InParameterEnabled);
    void set_GroupID(int InGroupID);
    void set_UnitID(int InUnitID);
    void set_SecurityLevel(int InSecurityLevel);

signals:
    void typeChanged();
    void enabledChanged();
    void groupIDChanged();
    void unitIDChanged();
    void securityLevelChanged();
    void parameterNameChanged();
    void shortDescriptionChanged();

private:
    int type;
    bool ParameterEnabled;
    int GroupID;
    int UnitID;
    int SecruityLevel;
    QString ParameterName;
    QString ShortDescription;
    int * CurrentValuePtr;
    int * LowerBoundPtr;
    int * UpperBoundPtr;
};

And my QML file:

Rectangle {
    id: frame
    property int val: SystemData.parameters[4].currentValue
    ...
}

It looks like I'm still getting an undefined value in this case. I'm trying to debug now, so that I can provide more information.

Était-ce utile?

La solution

It's very much possible. The key is to make sure you register the QML type and set the context property before setting the source on your QDeclarativeView.

Here's a working example -

main.cpp:

#include <QApplication>
#include <QtDeclarative>

class MyPropertyObject : public QObject {
    Q_OBJECT
    Q_PROPERTY(int value READ value CONSTANT)

public:
    MyPropertyObject(int value = -1) : m_value(value) { }

    int value() const {
        return m_value;
    }

private:
    int m_value;
};

class MyObject : public QObject {
    Q_OBJECT
    Q_PROPERTY(QDeclarativeListProperty<MyPropertyObject> props READ props CONSTANT)

public:

    MyObject() {
        m_props.append(new MyPropertyObject(55));
        m_props.append(new MyPropertyObject(44));
        m_props.append(new MyPropertyObject(33));
    }

    QDeclarativeListProperty<MyPropertyObject> props() {
        return QDeclarativeListProperty<MyPropertyObject>(this, m_props);
    }

private:
    QList<MyPropertyObject *> m_props;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QDeclarativeView view;
    view.engine()->rootContext()->setContextProperty(QLatin1String("tester"), new MyObject);
    qmlRegisterType<MyPropertyObject>();
    view.setSource(QUrl("qrc:///qml/main.qml"));
    view.setResizeMode(QDeclarativeView::SizeRootObjectToView);
    view.resize(300, 300);
    view.show();

    return a.exec();
}

#include "main.moc"

main.qml:

import QtQuick 1.1

Rectangle {
    property variant foo: tester.props[2].value

    Text {
        anchors.centerIn: parent
        text: parent.foo
    }
}

Note: read the docs for the QDeclarativeListProperty constructors. The one I'm using for this example is not the preferred one, but is good for quick prototypes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top