1
votes

I have a main.qml and inside that i have two banners(titlebanner and bottombanner) as shown in below.

Window {
    id: main
    visible: true

    Image {
        source: "qrc:/banner.png"
        anchors.fill: parent
    }

    TitleBanner {
        x:0
        y:10
    }

    BottomBanner {
        x:0
        y:420
    }
}

In TitleBanner.qml, i have below code

Item {
    Rectangle {
        id : id_title_banner

        property real value : titlebanner.title

        Image {
            source: "qrc:/banner_title.png";
        }

        //todo:: some animation stuffs on 'value' later
    }
}

In BottomBanner.qml, i have below code

Item {
    Rectangle {
        id : id_bottom_banner

        property real value : bottombanner.title

        Image {
            source: "qrc:/banner_bottom.png";
        }

        //todo:: some animation stuffs on 'value' later
    }
}

In C++ side, I am keeping two separate objects(for later flexibility) for both title banner and bottom banner. I set the root context property to expose the title banner objects from C++ to qml as below

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

   //create title banner object
   CTitleBanner *objTitleBanner = new CTitleBanner();

   //create bottom banner object
   CBottomBanner *objBottomBanner = new CBottomBanner();

   QQmlApplicationEngine engine;
   engine.rootContext()->setContextProperty("titlebanner", objTitleBanner);

   engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

   return app.exec();

}

My question is, how can we set context property for both titlebanner and bottombanner qml files separately instead of setting it to root context ? My concern is at later point if more banner comes, I set it to rootContext. Is it a proper way of doing ? How can we create seperate context for each banner ?

1
"it replaces above context property." Does it? I don't want to try it. If so. why don't you create a QObject contextData which has two properties: titlebanner and bottombanner which you set to be (by coincidence maybe?) your two original banner objects. However I think the answer to my initial question should be "no". - derM
@derM, sorry there was a correction in my question, I have edited the same. Yes. your point is correct it won't replace the previous context i tried the same. Please see my edited question. - GUI-Novice
I don't get your new question. How many banners will there be? And what impact will C++ have on this? You should strive to keep your C++ part to be as immutable as possible since QML is more flexible. Create a stable data model in C++, do the magic of visual representation in QML only. You might create some kind of content model in C++ if e.g. database access might be necessary. The C++ part should not know what is in the view. - derM
@derM, In my above example I am setting the contextProperty for root context. So I can access the banner object from all my qml files. For example, In BottomBanner.qml file I can access 'objTitleBanner' also. I am thinking is this is a preferred way of doing ?. Later point, I am planning to add more banners (say around 20 banners ). So finally we can access all banner object from any qml file. I don't know is this is an overhead for qt. is this so ? So I am thinking can we set a context specific to a qml file. For example from TitleBanner.qml I can only have access to 'objTitleBanner'. - GUI-Novice
Setting context properties is really only setting properties to the very root of your QML object tree. This means, QML will follow the regular name resolution algorithm (looking in the current scope, looking in the files root scope, looking in the root scope of the file that instantiates that file e.t.c until it reaches the root context - or fails). Within one scope, the lookup should be fast since it is (afaik) implemented as a map of some sort. Having 20 context properties is less a problem, than trying to access it from deeply nested objects. - derM

1 Answers

2
votes

Your assumption:

it replaces above context property.

is wrong:

// in main.cpp
QObject* obj1 = new QObject();
QObject* obj2 = new QObject();

engine.rootContext()->setContextProperty("obj1", obj1);
engine.rootContext()->setContextProperty("obj2", obj2);

qDebug() << "obj1" << obj1 << engine.rootContext()->contextProperty("obj1").value<QObject*>();
qDebug() << "obj2" << obj2 << engine.rootContext()->contextProperty("obj2").value<QObject*>();

// in main.qml
Component.onCompleted: console.log(obj1, obj2)

// output:
obj1 QObject(0x22d8c768) QObject(0x22d8c768)
obj2 QObject(0x22d8c778) QObject(0x22d8c778)
qml: QObject(0x22d8c768) QObject(0x22d8c778)

Both objects are there, with the right identifier.


Personally I don't like contextProperties since they are easily to be shadowed e.t.c. - I rather register my CPP models as singletons so I can import them at the places where I really want to have access to them. Though there are downsides of those singletons. (e.g. qmlscene will fail to import them)