简体   繁体   中英

How to create custom Quick QML Item with predefided states

I am quite new to Qt, so I am probably asking a pretty obvious question.

I would like to create a super type for all of my custom QML GUI elements that I want to create in C++. This super type is supposed to add predefined states to a QML Item. Something alike to this:

    import StatedGuiElement 1.0
    import QtQuick 2.0

    Item {
        width: 300; height: 200

        StatedGuiElement {
            id: aStatedGuiElement
            anchors.centerIn: parent
            width: 100; height: 100
            //some visible Custom Gui Elements
    states:[
        State {
            name: "A_STATE"

        },
        State {
            name: "ANOTHER_STATE"
        }]
}

I know how to create a simple custom Item from this tutorial ( http://doc.qt.io/qt-5/qtqml-tutorials-extending-qml-example.html ). I guess the states could be defined by using an enum in the C++ class which inherits from QQuickItem . However, this tutorial does not show how to create more complex Qt Quick elements like the state list.

class StatedGuiElement : public QQuickItem
{
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName)
    //pass States via Q_PROPERTY?
public:
    //define Enum for fixed States here?
    //ENUM STATES {A_STATE, ANOTHER_STATE}
    StatedGuiElement( QQuickItem *parent = 0);

    QString name() const;
    void setName(const QString &name);


private:
    QString m_name;
    //Some List of States?


signals:

public slots:
};

So the questions I am wondering about are as follows:

  • Is it even possible to predefine QML State types and use them in multiple elements?
  • How do I add complex QML types like State Lists in a C++ class such as StatedGuiElement ?

First you create your StatedGuiElement as a QQuickItem subclass.

Then you crate a StatedGuiElement.qml , import the package that contains the C++ element, make a StatedGuiElement {} inside, add your states in QML to it, then you can use StatedGuiElement in your project. It will be the one with the QML extra stuff predefined in it.

This assumes the element actually has things you need to implement in C++. If not then it would not make sense to have a C++ element at all. I am not sure whether old C++ state classes will work with QML, probably not, and using the QML states from C++ will be anything but convenient, so you really should do the states in QML, on top of whatever C++ stuff you may have.

It is possible to define your properties once and use them im multiple elements, if you nest your QML elements inside a super-type QML element where you have all your states defined. Child elements can access the parent parameters.

Alternatively, you can also just simply set the context property for each QML which should use the data like this in C++:

QQuickView view;

QStringList data;

// fill the list with data via append()

view.rootContext()->setContextProperty("dataList", QVariant::fromValue(data));

// now the QML can freely use and access the list with the variable name "dataList"

view.setSource(QUrl::fromLocalFile("MyItem.qml"));
view.show();

In the QML-side, you can also declare a custom property which holds the names of the states.

Item {
    property variant state_list: ["element1", "element2", "element3"]
    // or if you defined a list in the C++ part as a context property
    // you can use this instead:
    // property variant state_list: dataList

    states: [
        State {
            name: state_list[0]
        },

        State {
            name: state_list[1]
        },

        // and so on
    ]
}

If you need a property that is a list of elements, i..e. states being a list of State objects, then you can do this in C++ using the QQmlListProperty type.

You need a QObject derived type for the list element type.

Example

class Entry : public QObject
{
    // the list entry element's API
};

class MyItem : public QQuickItem
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<Entry> entries READ entries)


public:
    QQmlListProperty<Entry> entries() const {
        return QQmlListProperty<Entry>(this, m_entries);
    }

private:
    QList<Entry*> m_entries;
};

Register both with qmlRegisterType()

In QML

MyItem {
    entries: [
        Entry {
        },  
        Entry {
        }
    ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM