我希望Flow
从左到右添加对象,但每行都在右边对齐。
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
}
}
}
我将Flow
向右对齐,但其中的行始终从Flow
的左边缘开始。我可以设置
layoutDirection: Qt.RightToLeft
将行与右对齐,但项目的顺序也会相反。
如果我反转模型(在此示例中可以通过调用reverse()
来调用ListModel
,我需要撤消ProxyModel
)a
将在左侧,但行没有问题。
我怎么能得到这样的东西?
答案 0 :(得分:1)
import QtQuick 2.5
import QtQuick.Controls 2.1
ApplicationWindow {
id: root;
width: 640
height: 480
visible: true
Rectangle {
z: -1
color: "#80000000"
width: flow.width
height: flow.height
anchors.centerIn: flow
}
Flow {
id: flow
width: 400
anchors.right: parent.right
spacing: 2
Repeater {
id: repeater
property real remainingRowSpace: flow.width
property real indexOfFirstItemInLastRow: 0
model: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q']
delegate: Rectangle {
property real buttonWidth: (83 * (model.index + 1)) % 100 + 30
color: "#80000000"
width: buttonWidth
height: childrenRect.height
Button {
x: parent.width - width
text: modelData
width: parent.buttonWidth
}
}
onItemAdded: {
var spacing = parent.spacing
// Check if new row.
if (item.width > remainingRowSpace) {
// Increase width of first item push row right.
itemAt(indexOfFirstItemInLastRow).width += remainingRowSpace
// Reset available space
remainingRowSpace = parent.width
// Store index of item
indexOfFirstItemInLastRow = index
// Don't need to subtract spacing for the first item
spacing = 0
}
remainingRowSpace -= (item.width + spacing)
// Handle when no more rows will be created.
if (index === repeater.count - 1) {
itemAt(indexOfFirstItemInLastRow).width += remainingRowSpace
}
}
}
}
}
它不是一个多功能或动态的解决方案,但它有效。
答案 1 :(得分:0)
这仍然是一项正在进行中的工作,但可能仍适用于某些人
正如 Tony Clifton 的解决方案一样,它使用Repeater
及其onItemAdded
- 方法,但使用Qt.binding
来保存更多动态。 Tony Clifton 的解决方案并不优越,选择可能取决于用例。
上升空间:
Item
- 宽度缺点:
当与ListModel
一起使用并且新条目正在insert()
时,两种解决方案都无法正常工作。当模型被完全替换时(例如JSArray
和手动调用modelChanged()
),两种解决方案都应该有效。
在某种意义上,这两个解决方案都不是Flow
,因为Repeater
负责布局,所以你可以抛出任意对象。因此Repeater
必须创建Item
s。我没有使用ObjectModel
。摆脱中继器将是我最后的关注点。
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'
}
}
这背后的想法是在添加对象时初始化锚点的绑定,如果有足够的空间,我将每个Item
锚定到右侧或它的后继者。<登记/>
我还将Item
的底部锚定在它的旁边,如果它在他旁边,或者它的顶部,如果它开始一个新行。如果它没有继承者,它将被锚定到父母的底部
后一个事实,使这个奇怪的结构有两个必要的封闭Item
。外部将真正包围一切,并动态增长,但这不是那个,我锚定整个链,当我锚定到底部。如果我根据height
更改childrenRect.height
,我会在具有奇怪效果的绑定循环中结束,因为Items的y值不会保持不变。最初它会起作用,但是当项目因尺寸变化而移动时,它会破裂。