Qml 流程的反向布局顺序

Qml 流程的反向布局顺序,qml,qt5,qtquick2,Qml,Qt5,Qtquick2,我想让流从左到右添加对象,但每一行都与右对齐 import QtQuick 2.0 import QtQuick.Controls 2.0 Flow { width: 400 anchors.right: parent.right spacing: 2 Repeater { model: ['a', 'b', 'c', 'd', 'e', 'f', 'g'] delegate: Button { text:

我想让
从左到右添加对象,但每一行都与右对齐

import QtQuick 2.0
import QtQuick.Controls 2.0
Flow {
    width: 400
    anchors.right: parent.right
    spacing: 2
    Repeater {
        model: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
        delegate: Button {
            text: modelData
            width: (83 * (model.index + 1)) % 100 + 30
        }
    }
}
我将
向右对齐,但其中的行始终从
的左边缘开始。我可以设定

layoutDirection: Qt.RightToLeft
这将使行向右对齐,但项目的顺序也将颠倒

如果我反转模型(在本例中,可以通过调用
reverse()
,使用
ListModel
,我将需要一个反转的
ProxyModel
a
将位于左侧,但行的顺序不正确

我怎样才能实现这样的目标?

导入QtQuick 2.5
导入QtQuick.Controls 2.1
应用程序窗口{
id:根;
宽度:640
身高:480
可见:正确
长方形{
z:-1
颜色:“8000000”
宽度:flow.width
高度:flow.height
.centerIn:flow
}
流动{
id:流量
宽度:400
anchors.right:父项.right
间距:2
中继器{
id:中继器
属性real remainingRowSpace:flow.width
属性不动产indexOfFirstItemInLastRow:0
模型:['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q']
代表:矩形{
不动产按钮宽度:(83*(model.index+1))%100+30
颜色:“8000000”
宽度:按钮宽度
身高:childrenRect.height
钮扣{
x:parent.width-宽度
文本:modelData
宽度:parent.buttonWidth
}
}
他说:{
变量间距=父级间距
//检查是否有新行。
如果(item.width>remainingRowSpace){
//增加第一个项目向右推行的宽度。
itemAt(indexOfFirstItemInLastRow).宽度+=剩余行空间
//重置可用空间
remainingRowSpace=parent.width
//项目存储索引
indexOfFirstItemInLastRow=索引
//不需要减去第一项的间距
间距=0
}
剩余行空间-=(item.width+间距)
//将不创建更多行时的句柄。
if(index==repeater.count-1){
itemAt(indexOfFirstItemInLastRow).宽度+=剩余行空间
}
}
}
}
}
这不是一个非常通用或动态的解决方案,但它很有效

这仍然是一项正在进行的工作,但可能对某些人仍然有用

就像Tony Clifton的解决方案一样,它使用了
中继器
非定制的
-方法,但使用
Qt.binding
使事情更加动态它并不优于Tony Cliftons解决方案,选择可能取决于用例

正面:

  • 动态更改单个
    项目的宽度
  • 反向流动宽度的动态变化
缺点:

  • 首先填充底部一行。第一行可能未满(对于某些用例,这可能更好)
当与
ListModel
一起使用时,这两种解决方案都不起作用,并且正在插入一个新条目()
ed。当模型完全替换时(例如使用
JSArray
s和手动调用
modelChanged()
),这两种解决方案都应该起作用

这两种解决方案在某种意义上都不是
Flow
s,当
中继器处理布局时,您可以插入任意对象。因此,
中继器
必须创建
s。我没有让它与
对象模型
一起工作。摆脱中继器将是我最后的担忧

Item {
    id: root
    visible: false
    width: 400
    height: (rep.count > 0 ? rep.itemAt(0).y * -1 : 0)
    anchors.centerIn: parent
    property real spacing: 5
    Item {
        anchors.bottom: parent.bottom
        anchors.right: parent.right
        anchors.left: parent.left
        Repeater {
            id: rep
            model: ListModel {
                id: bm
                ListElement { text: "a" }
                ListElement { text: "b" }
                ListElement { text: "c" }
                ListElement { text: "d" }
                ListElement { text: "e" }
                ListElement { text: "f" }
                ListElement { text: "g" }
                ListElement { text: "h" }
                ListElement { text: "i" }
            }

            onItemAdded: {
                console.log(index, item, itemAt(index - 1))
                item.anchors.right = Qt.binding(
                            function() {
                                if (rep.count === index + 1) return parent.right
                                var neighbor = rep.itemAt(index + 1)
                                if (neighbor.x - item.width - root.spacing < 0) return parent.right
                                return rep.itemAt(index + 1).left
                            }
                            )
                item.anchors.bottom = Qt.binding(
                            function() {
                                if (rep.count === index + 1) return parent.bottom

                                var neighbor = rep.itemAt(index + 1)
                                if (neighbor.x - item.width - root.spacing < 0)
                                    return neighbor.top
                                return neighbor.bottom
                            }
                            )
                item.anchors.rightMargin = Qt.binding(
                            function() {
                                return (item.anchors.right === parent.right ? 0 : root.spacing)
                            }
                            )
                item.anchors.bottomMargin = Qt.binding(
                            function() {
                                return (item.anchors.bottom === rep.itemAt(index + 1).top ? root.spacing : 0)
                            }
                            )

            }
            delegate: Button {
                text: modelData
                property int count: 0
                width: (83 * (index + count + 1)) % 100 + 30
                onClicked: {
                    count++
                }
            }
        }
    }

    Rectangle {
        id: debug
        anchors.fill: parent
        color: 'transparent'
        border.color: 'red'
    }
}
项目{
id:根
可见:假
宽度:400
高度:(rep.count>0?rep.itemAt(0).y*-1:0)
anchors.centerIn:父对象
不动产间距:5
项目{
.bottom:parent.bottom
anchors.right:父项.right
anchors.left:parent.left
中继器{
id:rep
模型:ListModel{
id:bm
ListElement{text:“a”}
列表元素{text:“b”}
ListElement{text:“c”}
ListElement{text:“d”}
ListElement{text:“e”}
ListElement{text:“f”}
ListElement{text:“g”}
ListElement{text:“h”}
ListElement{text:“i”}
}
他说:{
日志(索引、项、项(索引-1))
item.anchors.right=Qt.binding(
函数(){
如果(rep.count==index+1)返回parent.right
var neighbor=rep.itemAt(索引+1)
if(neighbor.x-item.width-root.spating<0)返回parent.right
返回rep.itemAt(索引+1)。左侧
}
)
item.anchors.bottom=Qt.binding(
函数(){
如果(rep.count==index+1)返回parent.bottom
var neighbor=rep.itemAt(索引+1)
if(neighbor.x-item.width-root.space<0)
返回邻居
返回邻居。底部
}
)
item.anchors.rightMargin=Qt.binding(
函数(){
返回(i)