Qml c++ 不同的代表 qt mvc
Qml c++ diffrent delegates qt mvc
我如何在 qml 中为 ListView 使用不同的委托。例如,我有 QList 列表,SomeObject 有两个字段:类型(圆形、矩形等)和 someValue。我为此列表创建了 QListModel。我有不同的 qml 元素(circle.qml、rectangle.qml 等)。如何按类型查看项目的委托,并查看此委托中的字段 someValue。我可以在没有 table/list 的情况下定位这些代表吗?我想按坐标(x,y)定位它们。
- 您可以尝试一个可能符合您要求的qml Loader概念。基本上,您不能为单个视图定义多个委托。因此,将您的 Top Delegate 设置为加载程序并根据类型加载项目将帮助您解决这种情况。
- 也可以定位,您可以使用模型数据定义 x 和 y 位置。这样您就可以相应地对齐视图项。我在这种情况下使用了 Scrollview + Repeater
在此处共享了一个最小示例。为了简单起见,我将数据保存在 Qml ListModel 中。也可以对来自 c++ 模型的对象进行同样的操作。
Here 也将源作为 Qt 解决方案项目提供。
// ShapeModel.qml //
import QtQuick 2.15
import QtQml.Models 2.15
ListModel {
ListElement {
type: "circle"
val: "100"
xpos: 10
ypos: 10
}
ListElement {
type: "rectangle"
val: "30"
xpos: 100
ypos: 100
}
ListElement {
type: "circle"
val: "150"
xpos: 300
ypos: 450
}
ListElement {
type: "rectangle"
val: "20"
xpos: 500
ypos: 200
}
ListElement {
type: "circle"
val: "25"
xpos: 650
ypos: 100
}
ListElement {
type: "rectangle"
val: "60"
xpos: 600
ypos: 200
}
}
// main.qml //
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Qt MVC")
Component {
id: componentCircleId
Rectangle {
border.color: "blue"
border.width: 1
height: value
width: value
radius: value/2
}
}
Component {
id: componentRectangleId
Rectangle {
border.color: "orange"
border.width: 1
height: value
width: value
}
}
Component {
id: componentLoaderId
Loader {
property real value: val
x: xpos
y: ypos
sourceComponent: type === "circle" ?
componentCircleId : componentRectangleId
}
}
ScrollView {
id: scrollviewId
anchors.fill: parent
Repeater {
anchors.fill: parent
model: ShapeModel{}
delegate: componentLoaderId
onItemAdded: {
// scroll area computation
// Better solutions may be available
if(item.x+item.width > scrollviewId.contentWidth)
scrollviewId.contentWidth = item.x+item.width
if(item.y+item.height > scrollviewId.contentHeight)
scrollviewId.contentHeight = item.y+item.height
}
}
}
}
要根据角色有不同的代表(也可以根据行或列来完成),您应该使用 DelegateChooser
with DelegateChoice
:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import Qt.labs.qmlmodels 1.0
Window {
width: 640
height: 480
visible: true
ListModel {
id: shapeModel
ListElement {
type: "circle"
value: 100
x: 10
y: 10
}
ListElement {
type: "rectangle"
value: 30
x: 100
y: 100
}
ListElement {
type: "circle"
value: 30
x: 300
y: 450
}
ListElement {
type: "rectangle"
value: 20
x: 500
y: 200
}
ListElement {
type: "circle"
value: 25
x: 650
y: 100
}
ListElement {
type: "rectangle"
value: 60
x: 600
y: 200
}
}
Flickable {
anchors.fill: parent
contentWidth: contentItem.childrenRect.width
contentHeight: contentItem.childrenRect.height
Repeater {
model: shapeModel
delegate: DelegateChooser {
role: "type"
DelegateChoice {
roleValue: "rectangle"
Rectangle {
x: model.x
y: model.y
height: model.value
width: model.value
border.color: "orange"
border.width: 1
}
}
DelegateChoice {
roleValue: "circle"
Rectangle {
x: model.x
y: model.y
height: model.value
width: model.value
radius: model.value/2
border.color: "blue"
border.width: 1
}
}
}
}
}
}
它避免了加载程序的额外间接。
我如何在 qml 中为 ListView 使用不同的委托。例如,我有 QList
- 您可以尝试一个可能符合您要求的qml Loader概念。基本上,您不能为单个视图定义多个委托。因此,将您的 Top Delegate 设置为加载程序并根据类型加载项目将帮助您解决这种情况。
- 也可以定位,您可以使用模型数据定义 x 和 y 位置。这样您就可以相应地对齐视图项。我在这种情况下使用了 Scrollview + Repeater
在此处共享了一个最小示例。为了简单起见,我将数据保存在 Qml ListModel 中。也可以对来自 c++ 模型的对象进行同样的操作。 Here 也将源作为 Qt 解决方案项目提供。
// ShapeModel.qml //
import QtQuick 2.15
import QtQml.Models 2.15
ListModel {
ListElement {
type: "circle"
val: "100"
xpos: 10
ypos: 10
}
ListElement {
type: "rectangle"
val: "30"
xpos: 100
ypos: 100
}
ListElement {
type: "circle"
val: "150"
xpos: 300
ypos: 450
}
ListElement {
type: "rectangle"
val: "20"
xpos: 500
ypos: 200
}
ListElement {
type: "circle"
val: "25"
xpos: 650
ypos: 100
}
ListElement {
type: "rectangle"
val: "60"
xpos: 600
ypos: 200
}
}
// main.qml //
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Qt MVC")
Component {
id: componentCircleId
Rectangle {
border.color: "blue"
border.width: 1
height: value
width: value
radius: value/2
}
}
Component {
id: componentRectangleId
Rectangle {
border.color: "orange"
border.width: 1
height: value
width: value
}
}
Component {
id: componentLoaderId
Loader {
property real value: val
x: xpos
y: ypos
sourceComponent: type === "circle" ?
componentCircleId : componentRectangleId
}
}
ScrollView {
id: scrollviewId
anchors.fill: parent
Repeater {
anchors.fill: parent
model: ShapeModel{}
delegate: componentLoaderId
onItemAdded: {
// scroll area computation
// Better solutions may be available
if(item.x+item.width > scrollviewId.contentWidth)
scrollviewId.contentWidth = item.x+item.width
if(item.y+item.height > scrollviewId.contentHeight)
scrollviewId.contentHeight = item.y+item.height
}
}
}
}
要根据角色有不同的代表(也可以根据行或列来完成),您应该使用 DelegateChooser
with DelegateChoice
:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import Qt.labs.qmlmodels 1.0
Window {
width: 640
height: 480
visible: true
ListModel {
id: shapeModel
ListElement {
type: "circle"
value: 100
x: 10
y: 10
}
ListElement {
type: "rectangle"
value: 30
x: 100
y: 100
}
ListElement {
type: "circle"
value: 30
x: 300
y: 450
}
ListElement {
type: "rectangle"
value: 20
x: 500
y: 200
}
ListElement {
type: "circle"
value: 25
x: 650
y: 100
}
ListElement {
type: "rectangle"
value: 60
x: 600
y: 200
}
}
Flickable {
anchors.fill: parent
contentWidth: contentItem.childrenRect.width
contentHeight: contentItem.childrenRect.height
Repeater {
model: shapeModel
delegate: DelegateChooser {
role: "type"
DelegateChoice {
roleValue: "rectangle"
Rectangle {
x: model.x
y: model.y
height: model.value
width: model.value
border.color: "orange"
border.width: 1
}
}
DelegateChoice {
roleValue: "circle"
Rectangle {
x: model.x
y: model.y
height: model.value
width: model.value
radius: model.value/2
border.color: "blue"
border.width: 1
}
}
}
}
}
}
它避免了加载程序的额外间接。