【问题标题】:QML: Separators between list delegatesQML:列表代表之间的分隔符
【发布时间】:2021-07-08 19:09:22
【问题描述】:

有没有人找到一种的方法来在 QML 列表委托之间添加分隔符?

这里已经有一个非常相似的问题,但我的问题有点复杂:How to set custom separator between items of ListView

大多数时候,我会使用与那里的答案类似的东西:

ListView {
  delegate: ItemDelegate {
      ...
      Separator {
          anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
          visible: index < ListView.View.count
      }
  }
}

但是,根据设计和后端数据,我并不总是手头有 ListView/Repeater,而是需要在 ColumnLayout 中添加手动项目,或者混合来自转发器的一些项目和一些手动项目:

ColumnLayout {
    ItemDelegate {
        ...
    }
    Separator {
        Layout.fillWidth: true
    }
    ItemDelegate {
        ...
    }
}

现在,这两种方法都有效,但总是记住并输入分隔符非常烦人。经过大量尝试,我仍然无法找到一个可以处理它的组件。

我最接近这样的自定义布局组件(例如 ItemGroup.qml):

Item {
    default property alias content: layout.data

    ColumnLayout {
        id: layout
    }

    Repeater {
        model: layout.children
        delegate: Separator {
            parent: layout.children[index]
            anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
            visible: index < layout.children.length
        }
    }
}

现在这可以很好地手动将项目添加到这样的组,但同样在许多极端情况下它不会工作。例如,将Repeater 放入这样的ItemGroup 中也会为Repeater 创建一个分隔符(假设它继承了Item 并因此包含在children 中),这会导致一个看似浮动的分隔符太多的视觉故障。 .

有人想出一个更聪明的解决方案吗?

【问题讨论】:

    标签: qt qml


    【解决方案1】:

    我会尝试这种方法:

    1. 基于 ColumnLayout 制作自定义组件。
    2. 使用default property ... 语法将添加到其中的子代捕获到单独的列表属性中。
    3. 为 ColumnLayout 的 children 属性创建一个绑定,将默认属性列表中的每个真实子项与您的分隔符之一交错(使用 Component 声明它并使用 createObject() 创建每个子项)。

    这是一个工作示例:

    Separator.qml

    import QtQuick 2.0
    import QtQuick.Layouts 1.12
    
    Rectangle {
        Layout.fillWidth: true
        height: 1
        color: "red"
    }
    

    SeparatedColumnLayout.qml

    import QtQuick 2.15
    import QtQuick.Layouts 1.12
    
    ColumnLayout {
        id: layout
    
        default property list<Item> actualChildren
    
        property Component separatorComponent: Qt.createComponent("Separator.qml")
    
        children: {
            var result = [];
            for(var i = 0;i < actualChildren.length;++i) {
                result.push(actualChildren[i]);
                if (i < actualChildren.length - 1) {
                    result.push(separatorComponent.createObject(layout));
                }
            }
            return result;
        }
    }
    

    main.qml:

    import QtQuick 2.11
    import QtQuick.Window 2.11
    import QtQuick.Controls 2.4
    import QtQuick.Layouts 1.12
    
    ApplicationWindow {
        id: root
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        SeparatedColumnLayout {
            anchors.fill: parent
    
            Text {
                Layout.alignment: Qt.AlignHCenter
                text: "1"
            }
    
            Text {
                Layout.alignment: Qt.AlignHCenter
                text: "2"
            }
    
            Text {
                Layout.alignment: Qt.AlignHCenter
                text: "3"
            }
        }
    }
    

    结果:

    【讨论】:

    • 谢谢。在我使用data 而不是actualChildren 的问题中,这比我的示例要好一些。但是,我认为如果您将它与模型和手动项目混合使用,例如:```SeparatedColumnLayout { anchors.fill: parent Repeater { model: someModel Text { ... } } Text { ,我认为这会遇到同样的问题。 .. } } ``` 鉴于Repeater 也会出现在children 中。我想一种解决方法是检查该项目是否是中继器并跳过它,但是 afaik QML 没有提供确定它的方法。
    • instanceOf 运算符确实适用于组件。更多信息在这里:doc.qt.io/qt-5/qtqml-javascript-hostenvironment.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 2011-12-05
    • 1970-01-01
    • 2020-07-06
    • 2018-01-16
    相关资源
    最近更新 更多