在中继器内动态创建QML组件

时间:2019-02-21 06:48:25

标签: qt qml

我有一个ListModel,其中的元素具有有关数据类型的信息。我在Repeater中使用它来根据数据类型显示标签和组件,但是我不知道如何用a更改该TextField(在“ TEXT”数据类型的情况下);例如如果是“图像”,则按钮以调用文件对话框;或在我得到数据类型“ REAL”的情况下,带掩码的TextField为double。我该怎么做?

这是我的代码:

Repeater {
    id: r2
    model: ListModel {
      ListElement {
        nombreCampo: "Name"
        datoValor: "John Doe"
        tipoDato: "TEXT"
      }

      ListElement {
        nombreCampo: "Birth Date"
        datoValor: "19910101"
        tipoDato: "DATE"
      }

      ListElement {
        nombreCampo: "Photo"
        datoValor: "whatever.jpg"
        tipoDato: "IMAGE"
      }

      ListElement {
        nombreCampo: "Height"
        datoValor: "1.55"
        tipoDato: "REAL"
      }
    } 

    Text {
      text: nombreCampo
    }

    // this would go well with "TEXT" but not with "DATE" (where I'd prefer a datepicker) 
    // or with "IMAGE" (where I'd prefer a button to call a file dialog).
    // so this is the part where I need to generate it according to the case
    TextField {
        text: datoValor
        placeholderText: nombreCampo
        onTextChanged: {
            r2.model.get( index ).datoValor = this.text;
        }

    }
}

谢谢。

2 个答案:

答案 0 :(得分:2)

在Qt 5.12中,您可以使用DelegateChooser + DelegateChoice

import QtQuick 2.7
import QtQuick.Controls 2.3
import Qt.labs.qmlmodels 1.0

ApplicationWindow {
    width: 500
    height: 500
    visible: true

    Column {
        anchors.fill: parent
        Repeater {
            id: r2
            model: ListModel {
                ListElement {
                    nombreCampo: "Name"
                    datoValor: "John Doe"
                    tipoDato: "TEXT"
                }

                ListElement {
                    nombreCampo: "Birth Date"
                    datoValor: "19910101"
                    tipoDato: "DATE"
                }

                ListElement {
                    nombreCampo: "Photo"
                    datoValor: "whatever.jpg"
                    tipoDato: "IMAGE"
                }

                ListElement {
                    nombreCampo: "Height"
                    datoValor: "1.55"
                    tipoDato: "REAL"
                }
            }

            delegate: DelegateChooser {
                role: "tipoDato"
                DelegateChoice {
                    roleValue: "DATE"
    //                delegate: SomeDatePicker {
    //                    date: datoValor
    //                }
                }
                DelegateChoice {
                    roleValue: "IMAGE"
                    delegate: Button {
                        text: "Select image"
                    }
                }
                DelegateChoice {
                    roleValue: "TEXT"
                    delegate: TextField {
                        text: model.datoValor
                    }
                }
                DelegateChoice {
                    roleValue: "REAL"
                    delegate: TextField {
                        text: model.datoValor
                        // inputMask: ...
                    }
                }
            }
        }
    }
}

在早期版本中,您可以使用Loader,然后根据模型数据选择source / sourceComponent。

答案 1 :(得分:2)

我会在委托人内部使用加载程序。

Column{
    Repeater{
        model: // your model
        delegate: Loader{
            anchors{
                right: parent.right
                left: parent.left
            }
            sourceComponent: {
                if(tipoDato=== "TEXT")      {return textFieldComponent;}
                else if(tipoDato=== "DATE") {return datePickerComponent;}
                else if(tipoDato=== "IMAGE"){return imagePickerPickerComponent;}
                else if(tipoDato=== "REAL") {return floatPickerComponent;}
            }
        }
    }
}

// Component definition

Component{
    id: textFieldComponent
    // Define your component here
}
Component{
    id: datePickerComponent
    // Define your component here
}
Component{
    id: imagePickerPickerComponent
    // Define your component here
}
Component{
    id: floatPickerComponent
    // Define your component here
}

如果使用此示例,请考虑到必须定义每个组件的高度,并且必须定义顶部父列的宽度,以便正确呈现所有项目。