首页 > 解决方案 > 如何在qml中添加一个带有另一个组件的新组件作为参数

问题描述

我想要做的是在组件内创建一个新对象,这可以使用Componentqml 的组件来完成,但作为参数,我想传递另一个将在不同.qml文件中的组件。

我将说明我正在尝试做的事情。我已经完成了一个标签栏手风琴组件: 在此处输入图像描述

当我单击按钮时,我希望创建一个新选项卡,该选项卡将拥有自己的内容!

在此处输入图像描述

我提供了我在下面使用的代码:

import QtQuick 2.7
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.3

ApplicationWindow {
    visible: true
    width: 640
    height: 500
    title: qsTr("Tabbars")
    Button{
        id: button
        text: "add new tab dinamically"
        onClicked: item.createPanelItem()
        anchors.top:parent.top
        anchors.left:parent.left
        height: 20
        width: parent.width
    }
    Item{
        id:item
        //anchors.fill:parent
        anchors.top: button.bottom
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
            ScrollView{
                anchors.fill:parent
                Column {
                    id: column
                    width:item.width
                    property int currentItem: 0
                    PanelItem {
                        id:panel1
                        index:0
                        title: "Panel 1"
                        width:parent.width
                        content: Item {
                            property string title: "teste"
                            height: configContent.implicitHeight
                            width: configContent.implicitWidth
                            ColumnLayout{
                                id:configContent
                                anchors.topMargin: 10
                                anchors.bottomMargin: 10
                                anchors.fill:parent
                                TextField {
                                    id: companyNameText1
                                    placeholderText: qsTr("Company name")
                                    Layout.fillWidth: true
                                    selectByMouse: true
                                }
                                ComboBox {
                                    id: languagesComboBox1
                                    textRole: "text"
                                    objectName: "language"
                                    Layout.fillWidth: true
                                    model: ListModel {
                                        ListElement {text: QT_TR_NOOP("English"); oid: 0}
                                        ListElement {text: QT_TR_NOOP("Portuguese"); oid: 1}
                                        ListElement {text: QT_TR_NOOP("Spanish"); oid: 2}
                                        ListElement {text: QT_TR_NOOP("Italian"); oid: 3}
                                        ListElement {text: QT_TR_NOOP("French"); oid: 4}
                                        ListElement {text: QT_TR_NOOP("Portuguese(Brasil)"); oid: 5}
                                    }
                                }
                                ComboBox {
                                    id: devSndrModeComboBox1
                                    textRole: "text"
                                    objectName: "test_dev_sndr_mode"
                                    Layout.fillWidth: true
                                    model: ListModel {
                                        Component.onCompleted: {
                                            append({ text: QT_TR_NOOP("None"), oid: 0 })
                                            append({ text: QT_TR_NOOP("Subpanel"), oid: 1 })
                                            append({ text: QT_TR_NOOP("All"), oid: 2 })
                                        }
                                    }
                                }
                            }
                        }
//                        onResetOtherPanels: function(indexClicked){
//                            if()
//                        }
                    }
                    PanelItem {
                        id:panel2
                        index:1
                        title: "Panel 2"
                        width:parent.width
                        content: Item {
                            property string title: "teste"
                            height: configContent2.implicitHeight
                            width: configContent2.implicitWidth
                            ColumnLayout{
                                id:configContent2
                                anchors.fill:parent
                                ComboBox {
                                    id: sndrModeComboBox1
                                    textRole: "text"
                                    Layout.fillWidth: true
                                    model: ListModel {
                                        Component.onCompleted: {
                                            append({ text: QT_TR_NOOP("Preset"), oid: 0 })
                                            append({ text: QT_TR_NOOP("Programmed"), oid: 1 })
                                        }
                                    }
                                }
                            }
                        }
                        Component.onCompleted: {
                            //resetOtherAccordions.connect(panel1.resetHeight)
                            console.log("panel 2 height "+panel2.height)
                        }
                    }
                    PanelItem {
                        id:panel3
                        index:2
                        title: "Panel 3"
                        width:parent.width
                        content: Item {
                            property string title: "teste"
                            height: configContent3.implicitHeight
                            width: configContent3.implicitWidth
                            ColumnLayout{
                                id:configContent3
                                anchors.fill:parent
                                ComboBox {
                                    id: sndrModeComboBox2
                                    textRole: "text"
                                    Layout.fillWidth: true
                                    model: ListModel {
                                        Component.onCompleted: {
                                            append({ text: QT_TR_NOOP("Preset"), oid: 0 })
                                            append({ text: QT_TR_NOOP("Programmed"), oid: 1 })
                                        }
                                    }
                                }
                            }
                        }
                        Component.onCompleted: {
                            console.log("panel 3 height "+panel2.height)
                        }
                    }
                }
            }
            function createPanelItem(){
                panelItem.createObject(column,{title:qsTr("newTest"),index:4 /*,content: Item{}*/  })
            }
            Component {
                id: panelItem
                PanelItem {
                    title: qsTr("Teste")
                    width: parent.width
                }
            }
        }
}

PanelItem.qml

import QtQuick 2.7
import QtQuick.Layouts 1.2

Item {
    id: root
    property Component content
    property string title: "panel"
    property bool isSelected: false
    property int index: 0
    function toggleSelected() {
        root.isSelected = !root.isSelected
        if(root.isSelected){
            parent.currentItem = index
            for(var i = 0;i<parent.children.length;i++)
            {
                if(parent.children[i].index !== parent.currentItem && parent.children[i].isSelected)
                {
                    parent.children[i].toggleSelected()
                }
            }
        }
    }
    clip: true
    height: container.height + bar.height
    Rectangle{
        id: bar
        anchors {
            top: parent.top
            left: parent.left
            right: parent.right
        }
        height: 30
        color:  root.isSelected ? "#81BEF7" : "#CEECF5"
        Text {
            anchors.fill: parent
            anchors.margins: 10
            horizontalAlignment: Text.AlignLeft
            verticalAlignment: Text.AlignVCenter
            text: root.title
        }
        Text {
            anchors{
                right: parent.right
                top: parent.top
                bottom: parent.bottom
                margins: 10
            }
            horizontalAlignment: Text.AlignRight
            verticalAlignment: Text.AlignVCenter
            text: "^"
            rotation: root.isSelected ? "180" : 0
        }
        MouseArea {
            id:panelAreaClick
            anchors.fill: parent
            cursorShape: Qt.PointingHandCursor
            onClicked: function(){
                toggleSelected()
            }
        }
    }
    Rectangle{
        id: container
        anchors.top: bar.bottom
        anchors.left: parent.left
        anchors.right: parent.right
        height: loader.item && isSelected ? loader.item.height : 0
        Loader {
            id: loader
            visible: isSelected
            sourceComponent: content
            anchors.top: container.top
        }
        Behavior on height {
            PropertyAnimation { duration: 1000 }

        }
    }
}

我的大问题是我找不到content在 createObject 函数中提供某些东西的方法。

我知道我可以通过动态内容来content执行以下操作:

"content": "import QtQuick 2.0; Rectangle{}"

但这不是我想做的,因为我将在文件上创建一个组件,就像panellog.qml我想传递给content将要创建的新选项卡的参数一样。

标签: qtqml

解决方案


在您的内联组件中简单地指定它是最简单的:

        Component {
            id: panelItem
            PanelItem {
                title: qsTr("Teste")
                width: parent.width
                content: Item {}
            }
        }

或者您可以将类型设置为contentComponent以便您可以将一些其他内联组件传递给它,这...实际上几乎是一回事。这可能看起来有点太费力了,但实际上非常方便地以一种还可以让您访问当前组件范围的方式自定义内容。

这里的问题是 Qt 有一个有点阻碍的双向限制:

  • 您不能在命令式 (JS) 代码中使用声明性组件语法
  • 您不能以声明方式实例化内联组件

意思就是:

  • 如果要引用声明性对象,则必须使用其 id 或属性来执行此操作 - 它仅适用于标识符,而不适用于对象文字/实例

  • 如果你想创建一个对象,它必须在一个专用的 qml 文件中


推荐阅读