QML Alias of tab components

2019-06-11 08:18发布

I'm trying to make alias of a component contained inside a tab element but without success. Even this small example does not work :

Tab 
{
    id: tab1
    title:'tab1'

    property alias tab1Text: test.text

    Text {
        id:test
        text:'Test123'
    }    
}

I got this error :

property alias tab1Text: test.text

Can somebody indicate me where is the issue and how can I fix it ?

标签: qt qml
3条回答
Viruses.
2楼-- · 2019-06-11 09:03

The error occurs since the target of your alias declaration is not valid.

In QML you need to distinguish between Object and Component and what you have is not always transparent to the user.

Sometimes you can find in the documentation a property like sourceComponent

sourceComponent: Component

If you assign something to it, like:

sourceComponent: Item {}

the Item won't be instantiated. Instead a Component for this Item is implicitly created that can then be used to create Items. But since there is no instance of the Item yet, you also can't access any properties inside this non-existent Item.

Then in QML you have something called default property.
This property is the place to which all the subobjects are automatically assigned to.

Tab {
    Item {}
}

and

Tab {
    sourceComponent: Item {}
}

are equivalent. In most cases the default property is not of type Component, so the assigned thing is directly instantiated.


Now how to solve the problem? You might set active: true and read or write to theTab.item.theProperty using bindings, but you still can't alias to it since the syntax for alias only allows id.property and not id.someProperty.someNestedProperty.

But setting active: true implies that not only the properties are created, but all visual items, which is usually not desired. In my opinion, the best way is, to keep data and visual representation separated from each other:
You can have a ViewModel in which you have all the data stored, and you use the visual representation to bind to it. So the binding is initiated by the Tab to read (and possibly modify) the text. And your other object does the same, to the same property of the model object.

A model is not necessarily some sort of list of objects. It might be just one object with various properties for your view to display.

查看更多
一夜七次
3楼-- · 2019-06-11 09:08

You can create a string property in Tab and bind Text.text to it. Binding is created when Tab's dynamic content is loaded. No need to force loading of tabs with active property.

TabView {
    id: tabView

    function setTab2Text(txt) {
        tab2.tab2Text = txt
    }

    Tab
    {
        id: tab1
        title:'tab1'
        property string tab1Text: 'Test123'
        Text {
            id:test
            text: tab1.tab1Text
        }
    }
    Tab
    {
        id: tab2
        title:'tab2'
        property string tab2Text
        Text {
            id:test2
            text: tab2.tab2Text
        }
    }
    Component.onCompleted: setTab2Text('Test456')
}
查看更多
够拽才男人
4楼-- · 2019-06-11 09:10

You can't alias to a direct child of the Tab since its content is not loaded by default:

A Tab item inherits from Loader and provides a similar API.

Tabs are lazily loaded; only tabs that have been made current (for example, by clicking on them) will have valid content.

What you can do is using a property on item instead of an alias:

Tab {
    id: tab1
    title: 'tab1'
    active: true
    property string tab1Text: tab1.item ? tab1.item.text : ""

    Text {
        id: test
        text: 'Test123'
    }
}

But still it will be bound to the actual text only if the content is loaded (current Tab or with active: true).

You can also add an Item around your content:

Tab {
    id: tab1
    title: 'tab1'

    Item {
        property alias tab1Text: test.text

        Text {
            id: test
            text: 'Test123'
        }
    }
}

But still the alias will not be available outside of this Item (including at the root of the tab).

查看更多
登录 后发表回答