1
votes

I am trying to change the delegate of qml listview from C++ but currently I stuck at how to change the alias which represents the delegate property.

Update on details: I have multiple delegates in separated qml files, in my application there are many screens, each screen will have different UI of listview, what I want is something like:

Pass delegate file name to C++ function >>> C++ function set delegate property of listView (or thing like that) >>> listview loads corresponding delegate.

My qml file looks like:

Item {
    id: root
    property alias listViewDelegate: listView.delegate

    ListView{
        id: listView
        delegate: MyDelegate{} // I have MyDelegate.qml file, it's working well
        model: listModel
    }

    // List model
    MyListModel {
        id: listModel
    }
}

I tried to change listViewDelegate alias from C++ using setProperty() method but got no luck (error in fact).

qmlObj->setProperty("listViewDelegate", componentDelegate);

How to achieve this? Or anyone can suggest me the better method to achieve it? Thanks!

3

3 Answers

4
votes

I think that there is a better way to do this.

Steps:

1) create a model in c++ side.

class Model : public QObject {
  Q_OBJECT
  Q_PROPERTY(qint32 status READ status WRITE setStatus NOTIFY statusChanged)
public:
  Model(QObject *parent = Q_NULLPTR);
  ...
}

2) pass the Model Object to qml by setContextProperty

Model model;
engine.rootContext()->setContextProperty("model1", &model);

3) binding your delegate of ListView on Model.status

ListView {
    id: listview
    anchors.fill: parent
    spacing: 20
    model: listmodel
    delegate: model1.status === 0 ? delegate1 : delegate2
}

4) now you can change delegate by setStaus() in c++ side.

model.setStatus(1);
2
votes

The property listViewDelegate has to be assigned to the ListView, so that when you modify the ListViewDelegate property, the ListView will be notified of this and update the delegate.

Item {
    id: root
    property Component listViewDelegate: myDelegate

    MyDelegate { 
          id:  myDelegate
    }

    ListView{
        id: listView
        delegate: listViewDelegate
        model: listModel
    }

    // List model
    MyListModel {
        id: listModel
    }
}
0
votes

Thank everyone, I just figured out a way to do that by using javascript, seems complicated but it works.

I add this javascript function into my root Item

function loadListViewDelegate(file){
    var component = Qt.createComponent(file);
    if(component && (component.status === Component.Ready))
    {
        listView.delegate = component;
        return file;
    }
    return "";
}

Then I invoke this function from C++, with parameter is the delegate qml file. It looks like this:

QMetaObject::invokeMethod(qmlObj, "loadListViewDelegate", Q_RETURN_ARG(QVariant, returnedValue), Q_ARG(QVariant, "delegate_screen_home.qml"));

How to invoke qml javascript method