[Interest] Define map of static items in QML

Elvis Stansvik elvstone at gmail.com
Fri Jun 3 17:56:44 CEST 2016


2016-06-03 17:55 GMT+02:00 Elvis Stansvik <elvstone at gmail.com>:
> Hi Alejandro,
>
> I realized I never got back to this and answered you, sorry about that.
>
> 2016-04-02 17:02 GMT+02:00 Alejandro Exojo <suy at badopi.org>:
>> El Wednesday 30 March 2016, Elvis Stansvik escribió:
>>> > not at all if that suit you for your key, it's all good. objectname is
>>> > just a string property after all. id would be a bad idea, since it
>>> > depend on the context instance.
>>>
>>> Alright, then I think I'll do that, thanks.
>>
>> This was an interesting thread. Is surprising that such a simple thing can't
>> be done more elegantly. I've been trying to think of a "pretty" way, and it
>> took me a bit to do it in QML only. The only really good solution would
>> require some C++. Actually, a simple one would be to use
>>
>> Since the objectName is OK for you, a solution that looks more elegant to me,
>> would be laying out the objects directly under the default property of some
>> element:
>>
>> Root {
>>         A {objectName: "a"}
>>         B {objectName: "b"}
>>         C {objectName: "c"}
>> }
>>
>> Then I thought you could access them by using something like
>> QObject::findChild. Since that function is not exposed to QML, you would have
>> either to make a similar one and expose it yourself.
>>
>> I've tried to get a QML only solution that was pretty enough, and I've almost
>> failed, since I've hit several limitations of the language that would have
>> made this simpler.
>>
>> Attempt 1:
>>
>> // Helper.qml
>> QtObject {
>>     default property var stuff
>>     function get(name) {
>>         for (var i = 0; i < stuff.length; i++) {
>>             if (stuff[i].objectName == name)
>>                 return stuff[i];
>>         }
>>     }
>> }
>> // Now you could do this in main.qml
>> ApplicationWindow {
>>     visible: true
>>     Helper {
>>         id: pages // Here you would add the Foo{} and Bar{} "pages"
>>         QtObject {objectName: "foo"}
>>         QtObject {objectName: "bar"}
>>         QtObject {objectName: "baz"}
>>     }
>>     Component.onCompleted: {
>>         console.log(pages.get("foo"));
>>     }
>> }
>>
>> But no, doesn't work:
>>
>> https://bugreports.qt.io/browse/QTBUG-10822
>>
>> The default property gets overwritten each time, and it doesn't set a list.
>> Only the last one remains. Item has a default property like that (and even
>> QtObject could have it, probably left out for saving memory), but it's done in
>> C++.
>>
>> A possible workaround that would not be that nice here, because we don't want
>> an Item as a helper, we want a QtObject:
>>
>> http://lists.qt-project.org/pipermail/development/2013-October/013428.html
>>
>>
>> Attempt 2:
>>
>> Since the default property can't be used, surrender and use a named one when
>> assigning:
>>
>> // Helper.qml
>> QtObject {
>>     // Now the property is not default
>>     property var stuff
>>     // ...
>> }
>> // main.qml
>> ApplicationWindow {
>>     visible: true
>>     Helper {
>>         id: screens
>>         stuff: [
>>             QtObject {objectName: "foo"},
>>             QtObject {objectName: "bar"},
>>             QtObject {objectName: "baz"}
>>         ]
>>     }
>>     Component.onCompleted: {
>>         console.log(screens.get("foo"));
>>     }
>> }
>>
>> And this fails too:
>> main.qml:9 Cannot assign multiple values to a singular property
>>
>>
>> Attempt 3:
>>
>> OK, the Helper is easily fixable now:
>>
>> QtObject {
>>     property list<QtObject> stuff
>>     // ... same as before
>> }
>>
>> Now you can get the main as previously. This finally works.
>
> Thanks a lot for investigating these options. Your final solution is
> nice, but I agree it's suprising how hard this was to do in QML, and
> that the solution is still not 100% declarative.
>
> What I ended up doing was abandon the idea of naming my objects with,

*naming my objects with strings.

> and using the ObjectModel approach and giving each page an id instead.
> Simplified, something like this:
>
> Window {
>     visible: true
>
>     ObjectModel {
>         WelcomePage { id: welcomePage }
>         SettingsPage { id: settingsPage }
>         ScanPage { id: scanPage }
>     }
>
>     StackView {
>         id: stackView
>         anchors.fill: parent
>
>         initialItem: welcomePage
>     }
> }
>
> Then I can do e.g. stackView.push(scanPage) in other parts of my QML code.
>
> It still feels like a little like abusing ObjectModel, since it's
> meant to be used as a model for an item view, not as a general holder
> of items which you don't want to be visible.
>
> Cheers,
> Elvis
>
>>
>>
>> Again, if you had more possibilities in the QML language (like defining an
>> enumeration in QML, for example) you could think of other solutions.
>>
>> --
>> Alex (a.k.a. suy) | GPG ID 0x0B8B0BC2
>> http://barnacity.net/ | http://disperso.net
>> _______________________________________________
>> Interest mailing list
>> Interest at qt-project.org
>> http://lists.qt-project.org/mailman/listinfo/interest



More information about the Interest mailing list