Qt 动态创建QML状态

Qt 动态创建QML状态,qt,qml,Qt,Qml,我想制作一个图标组件,根据其状态更改其图片和颜色: StateIcon.qml: import QtQuick 2.0 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 Item { Layout.preferredWidth: appLayout.icon.prefWidth Layout.preferredHeight: appLayout.icon.prefHeight property varia

我想制作一个图标组件,根据其状态更改其图片和颜色:

StateIcon.qml:

import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0

Item {
    Layout.preferredWidth: appLayout.icon.prefWidth
    Layout.preferredHeight: appLayout.icon.prefHeight

    property variant stateImage: stateImageInstance
    Image {
        id: stateImageInstance
        width: appLayout.icon.prefWidth
        height: appLayout.icon.prefWidth

        sourceSize.width: width
        sourceSize.height: height
    }

    property variant imageOverlay: imageOverlayInstance
    ColorOverlay {
        id: imageOverlayInstance
        anchors.fill: stateImage
        source: stateImage
    }

    transitions: Transition {
        SequentialAnimation {
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 0; duration: 100
            }
            PropertyAction {
                target: stateImage; property: "source"
            }
            PropertyAction {
                target: imageOverlay; property: "color"
            }
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 1; duration: 100
            }
        }
    }
}
StateIcon {
    id: stateIcon
    states: [
        State {
            name: "state1";
            PropertyChanges {
                target: stateIcon.stateImage
                source: "qrc:/resources/icons/icon1.svg"
            }
            PropertyChanges {
                target: stateIcon.imageOverlay; color: "gray"
            }

        },
        State {
            name: "state2";
            PropertyChanges {
                target: stateIcon.stateImage
                source: "qrc:/resources/icons/icon2.svg"
            }
            PropertyChanges {
                target: stateIcon.imageOverlay; color: "green"
            }
        }
        ...
    ]

    state: "state1"
}
StateIcon {
    id: stateIcon
    rawStates: [
           {
               name: "state1",
               iconSource: "qrc:/resources/icons/state1.svg",
               color: "green"
           },
           {
               name: "state2",
               iconSource: "qrc:/resources/icons/state2.svg",
               color: "green"
           },
           ...
       ]

    state: "state1"
}
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0

Item {
    property variant rawStates

    Layout.preferredWidth: appLayout.icon.prefWidth
    Layout.preferredHeight: appLayout.icon.prefHeight

    Image {
        id: stateImage
        width: appLayout.icon.prefWidth
        height: appLayout.icon.prefWidth

        sourceSize.width: width
        sourceSize.height: height
    }

    ColorOverlay {
        id: imageOverlay
        anchors.fill: stateImage
        source: stateImage
    }

    states: [
        for(var i=0; i<rawStates.length; ++i) {
            ?
        }
    ]

    transitions: Transition {
        SequentialAnimation {
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 0; duration: 100
            }
            PropertyAction {
                target: stateImage; property: "source"
            }
            PropertyAction {
                target: imageOverlay; property: "color"
            }
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 1; duration: 100
            }
        }
    }
}
问题是我必须在组件实例中定义状态:

main.qml:

import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0

Item {
    Layout.preferredWidth: appLayout.icon.prefWidth
    Layout.preferredHeight: appLayout.icon.prefHeight

    property variant stateImage: stateImageInstance
    Image {
        id: stateImageInstance
        width: appLayout.icon.prefWidth
        height: appLayout.icon.prefWidth

        sourceSize.width: width
        sourceSize.height: height
    }

    property variant imageOverlay: imageOverlayInstance
    ColorOverlay {
        id: imageOverlayInstance
        anchors.fill: stateImage
        source: stateImage
    }

    transitions: Transition {
        SequentialAnimation {
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 0; duration: 100
            }
            PropertyAction {
                target: stateImage; property: "source"
            }
            PropertyAction {
                target: imageOverlay; property: "color"
            }
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 1; duration: 100
            }
        }
    }
}
StateIcon {
    id: stateIcon
    states: [
        State {
            name: "state1";
            PropertyChanges {
                target: stateIcon.stateImage
                source: "qrc:/resources/icons/icon1.svg"
            }
            PropertyChanges {
                target: stateIcon.imageOverlay; color: "gray"
            }

        },
        State {
            name: "state2";
            PropertyChanges {
                target: stateIcon.stateImage
                source: "qrc:/resources/icons/icon2.svg"
            }
            PropertyChanges {
                target: stateIcon.imageOverlay; color: "green"
            }
        }
        ...
    ]

    state: "state1"
}
StateIcon {
    id: stateIcon
    rawStates: [
           {
               name: "state1",
               iconSource: "qrc:/resources/icons/state1.svg",
               color: "green"
           },
           {
               name: "state2",
               iconSource: "qrc:/resources/icons/state2.svg",
               color: "green"
           },
           ...
       ]

    state: "state1"
}
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0

Item {
    property variant rawStates

    Layout.preferredWidth: appLayout.icon.prefWidth
    Layout.preferredHeight: appLayout.icon.prefHeight

    Image {
        id: stateImage
        width: appLayout.icon.prefWidth
        height: appLayout.icon.prefWidth

        sourceSize.width: width
        sourceSize.height: height
    }

    ColorOverlay {
        id: imageOverlay
        anchors.fill: stateImage
        source: stateImage
    }

    states: [
        for(var i=0; i<rawStates.length; ++i) {
            ?
        }
    ]

    transitions: Transition {
        SequentialAnimation {
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 0; duration: 100
            }
            PropertyAction {
                target: stateImage; property: "source"
            }
            PropertyAction {
                target: imageOverlay; property: "color"
            }
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 1; duration: 100
            }
        }
    }
}
现在我想知道,在某些数组中是否可以只定义状态名称、颜色和源:

main.qml:

import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0

Item {
    Layout.preferredWidth: appLayout.icon.prefWidth
    Layout.preferredHeight: appLayout.icon.prefHeight

    property variant stateImage: stateImageInstance
    Image {
        id: stateImageInstance
        width: appLayout.icon.prefWidth
        height: appLayout.icon.prefWidth

        sourceSize.width: width
        sourceSize.height: height
    }

    property variant imageOverlay: imageOverlayInstance
    ColorOverlay {
        id: imageOverlayInstance
        anchors.fill: stateImage
        source: stateImage
    }

    transitions: Transition {
        SequentialAnimation {
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 0; duration: 100
            }
            PropertyAction {
                target: stateImage; property: "source"
            }
            PropertyAction {
                target: imageOverlay; property: "color"
            }
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 1; duration: 100
            }
        }
    }
}
StateIcon {
    id: stateIcon
    states: [
        State {
            name: "state1";
            PropertyChanges {
                target: stateIcon.stateImage
                source: "qrc:/resources/icons/icon1.svg"
            }
            PropertyChanges {
                target: stateIcon.imageOverlay; color: "gray"
            }

        },
        State {
            name: "state2";
            PropertyChanges {
                target: stateIcon.stateImage
                source: "qrc:/resources/icons/icon2.svg"
            }
            PropertyChanges {
                target: stateIcon.imageOverlay; color: "green"
            }
        }
        ...
    ]

    state: "state1"
}
StateIcon {
    id: stateIcon
    rawStates: [
           {
               name: "state1",
               iconSource: "qrc:/resources/icons/state1.svg",
               color: "green"
           },
           {
               name: "state2",
               iconSource: "qrc:/resources/icons/state2.svg",
               color: "green"
           },
           ...
       ]

    state: "state1"
}
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0

Item {
    property variant rawStates

    Layout.preferredWidth: appLayout.icon.prefWidth
    Layout.preferredHeight: appLayout.icon.prefHeight

    Image {
        id: stateImage
        width: appLayout.icon.prefWidth
        height: appLayout.icon.prefWidth

        sourceSize.width: width
        sourceSize.height: height
    }

    ColorOverlay {
        id: imageOverlay
        anchors.fill: stateImage
        source: stateImage
    }

    states: [
        for(var i=0; i<rawStates.length; ++i) {
            ?
        }
    ]

    transitions: Transition {
        SequentialAnimation {
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 0; duration: 100
            }
            PropertyAction {
                target: stateImage; property: "source"
            }
            PropertyAction {
                target: imageOverlay; property: "color"
            }
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 1; duration: 100
            }
        }
    }
}
StateIcon.qml
中,使用
rawStates
属性动态定义
states
属性

也许是这样的:

StateIcon.qml:

import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0

Item {
    Layout.preferredWidth: appLayout.icon.prefWidth
    Layout.preferredHeight: appLayout.icon.prefHeight

    property variant stateImage: stateImageInstance
    Image {
        id: stateImageInstance
        width: appLayout.icon.prefWidth
        height: appLayout.icon.prefWidth

        sourceSize.width: width
        sourceSize.height: height
    }

    property variant imageOverlay: imageOverlayInstance
    ColorOverlay {
        id: imageOverlayInstance
        anchors.fill: stateImage
        source: stateImage
    }

    transitions: Transition {
        SequentialAnimation {
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 0; duration: 100
            }
            PropertyAction {
                target: stateImage; property: "source"
            }
            PropertyAction {
                target: imageOverlay; property: "color"
            }
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 1; duration: 100
            }
        }
    }
}
StateIcon {
    id: stateIcon
    states: [
        State {
            name: "state1";
            PropertyChanges {
                target: stateIcon.stateImage
                source: "qrc:/resources/icons/icon1.svg"
            }
            PropertyChanges {
                target: stateIcon.imageOverlay; color: "gray"
            }

        },
        State {
            name: "state2";
            PropertyChanges {
                target: stateIcon.stateImage
                source: "qrc:/resources/icons/icon2.svg"
            }
            PropertyChanges {
                target: stateIcon.imageOverlay; color: "green"
            }
        }
        ...
    ]

    state: "state1"
}
StateIcon {
    id: stateIcon
    rawStates: [
           {
               name: "state1",
               iconSource: "qrc:/resources/icons/state1.svg",
               color: "green"
           },
           {
               name: "state2",
               iconSource: "qrc:/resources/icons/state2.svg",
               color: "green"
           },
           ...
       ]

    state: "state1"
}
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0

Item {
    property variant rawStates

    Layout.preferredWidth: appLayout.icon.prefWidth
    Layout.preferredHeight: appLayout.icon.prefHeight

    Image {
        id: stateImage
        width: appLayout.icon.prefWidth
        height: appLayout.icon.prefWidth

        sourceSize.width: width
        sourceSize.height: height
    }

    ColorOverlay {
        id: imageOverlay
        anchors.fill: stateImage
        source: stateImage
    }

    states: [
        for(var i=0; i<rawStates.length; ++i) {
            ?
        }
    ]

    transitions: Transition {
        SequentialAnimation {
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 0; duration: 100
            }
            PropertyAction {
                target: stateImage; property: "source"
            }
            PropertyAction {
                target: imageOverlay; property: "color"
            }
            NumberAnimation {
                target: stateImage; property: "scale"
                to: 1; duration: 100
            }
        }
    }
}
导入QtQuick 2.0
导入QtQuick.Layouts 1.3
导入QtGraphicalEffects 1.0
项目{
属性变量状态
Layout.preferredWidth:appLayout.icon.prefWidth
Layout.preferredHeight:appLayout.icon.prefHeight
形象{
id:stateImage
宽度:appLayout.icon.prefWidth
高度:appLayout.icon.prefWidth
sourceSize.width:宽度
sourceSize.height:高度
}
彩色套印{
id:imageOverlay
anchors.fill:stateImage
资料来源:stateImage
}
国家:[
对于(var i=0;i可能这有助于您:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQml 2.2

ApplicationWindow {
    id: mainWindow
    visible: true
    minimumWidth: 500
    minimumHeight: 500

    Row {
        Rectangle {
            id: rect
            width: 100
            height: 100

            Text {
                anchors.fill: parent
                text: parent.state
            }

            property var myStates: []
            states: myStates

            onStateChanged: console.log(Object.keys(rect.states))
        }

        Button {
            text: 'add state'
            onClicked: {
                rect.myStates.push(statePrototype.createObject(rect,
                                                           {
                                                               name: 'state' + count,
                                                               color: Qt.rgba(Math.random(count),
                                                                              Math.random(count),
                                                                              Math.random(count),
                                                                              Math.random(count))
                                                           }))
                rect.myStatesChanged()
                count++
            }
        }

        Button {
            text: 'change state'
            onClicked: {
                rect.state = 'state' + (count1 % count)
                count1++
            }
        }

    }

    property int count: 0
    property int count1: 0
    Component {
        id: statePrototype
        State {
            id: st
            property color color
            PropertyChanges {
                target: rect
                color: st.color
            }
        }
    }
}
直接将
State
s添加到
states
似乎不太容易。在自定义
属性var myStates
上多走了一英里后,它突然起作用了。别忘了告诉所有人,在添加了一些东西之后,
mystateshanged()

再次编辑,使用JS对象列表和实例化器。方法相同

也许这对你有帮助:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQml 2.2

ApplicationWindow {
    id: mainWindow
    visible: true
    minimumWidth: 500
    minimumHeight: 500

    Row {
        Rectangle {
            id: rect
            width: 100
            height: 100

            Text {
                anchors.fill: parent
                text: parent.state
            }

            property var myStates: []
            states: myStates

            onStateChanged: console.log(Object.keys(rect.states))
        }

        Button {
            text: 'add state'
            onClicked: {
                rect.myStates.push(statePrototype.createObject(rect,
                                                           {
                                                               name: 'state' + count,
                                                               color: Qt.rgba(Math.random(count),
                                                                              Math.random(count),
                                                                              Math.random(count),
                                                                              Math.random(count))
                                                           }))
                rect.myStatesChanged()
                count++
            }
        }

        Button {
            text: 'change state'
            onClicked: {
                rect.state = 'state' + (count1 % count)
                count1++
            }
        }

    }

    property int count: 0
    property int count1: 0
    Component {
        id: statePrototype
        State {
            id: st
            property color color
            PropertyChanges {
                target: rect
                color: st.color
            }
        }
    }
}
直接将
State
s添加到
states
似乎不太容易。在自定义
属性var myStates
上多走了一英里后,它突然起作用了。别忘了告诉所有人,在添加了一些东西之后,
mystateshanged()

再次编辑,使用JS对象列表和实例化器。方法相同


我将使用普通的javascript关联数组,而不是使用
States
。 你不能使用
转换
,但你可以使用
行为
来代替。行为不能做任何事情,但大多数时候已经足够了

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQml 2.2

ApplicationWindow {
    id: mainWindow
    visible: true
    minimumWidth: 500
    minimumHeight: 500

    Row {
        Rectangle {
            id: rect
            width: 100
            height: 100

            property var stateDescriptors: {
                'state0': {color: 'green'},
                'state1': {color: 'red'},
                'state2': {color: 'blue'},
                'state3': {color: 'purple'},
                'state4': {color: 'orange'}
            }
            property string iconState: "state0"

            Text {
                anchors.fill: parent
                text: parent.iconState
            }
            color: stateDescriptors[iconState].color
            Behavior on iconState {
                SequentialAnimation {
                    NumberAnimation {
                        target: rect; property: "scale"
                        to: 0; duration: 100
                    }
                    PropertyAction { } //actually change the iconState here, since the color is binded to it, it will also change between the 2 scale animations
                    NumberAnimation {
                        target: rect; property: "scale"
                        to: 1; duration: 100
                    }
                }
            }
        }

        Button {
            text: 'change state'
            property int count: 0
            onClicked: {
                count = (count + 1) % Object.keys(rect.stateDescriptors).length
                rect.iconState = 'state' + count
            }
        }
    }
}

我将使用普通的javascript关联数组,而不是使用
States
。 你不能使用
转换
,但你可以使用
行为
来代替。行为不能做任何事情,但大多数时候已经足够了

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQml 2.2

ApplicationWindow {
    id: mainWindow
    visible: true
    minimumWidth: 500
    minimumHeight: 500

    Row {
        Rectangle {
            id: rect
            width: 100
            height: 100

            property var stateDescriptors: {
                'state0': {color: 'green'},
                'state1': {color: 'red'},
                'state2': {color: 'blue'},
                'state3': {color: 'purple'},
                'state4': {color: 'orange'}
            }
            property string iconState: "state0"

            Text {
                anchors.fill: parent
                text: parent.iconState
            }
            color: stateDescriptors[iconState].color
            Behavior on iconState {
                SequentialAnimation {
                    NumberAnimation {
                        target: rect; property: "scale"
                        to: 0; duration: 100
                    }
                    PropertyAction { } //actually change the iconState here, since the color is binded to it, it will also change between the 2 scale animations
                    NumberAnimation {
                        target: rect; property: "scale"
                        to: 1; duration: 100
                    }
                }
            }
        }

        Button {
            text: 'change state'
            property int count: 0
            onClicked: {
                count = (count + 1) % Object.keys(rect.stateDescriptors).length
                rect.iconState = 'state' + count
            }
        }
    }
}

您是否尝试了一个
实例化器
来创建状态,并将它们填充到
状态
?我不知道这是否可行,但现在几乎没有时间尝试。我尝试使用
组件
创建
状态
数组。但我没有成功。也许其他人能够做到。为什么需要使用states在这里?你可以用一个关联数组属性很容易地做到这一点。@GrecKo你能写一个小例子吗?你有没有试过用
实例化器
来创建状态,并将它们填充到
状态中
?我不知道这是否可行,但现在几乎没有时间去尝试。我试过用来创建
状态
数组de>组件
。但我没有成功。也许其他人也能做到。为什么需要在这里使用状态?使用关联数组属性可以轻松做到这一点。@GrecKo你能写一个小示例吗?