【问题标题】:Two-dimensional table with nested scrolling areas in QMLQML中具有嵌套滚动区域的二维表
【发布时间】:2015-04-17 13:40:54
【问题描述】:

我想在 QML 中创建一个电视节目表,其中纵轴是频道列表,横轴是基于时间的。例如像


(来源:zappware.com

最初,我创建了

  • 一个垂直的 ListView
    • model = 频道列表
    • delegate = 水平 ListView
  • 每个水平的 ListView 都有
    • model = 事件列表
    • delegate = 宽度与事件持续时间成正比的项目

到目前为止一切顺利。唯一的缺点是水平的 ListView 一个一个滚动,而它们应该一起滚动。

因此,不知何故,每个水平 ListView 的 contentX 属性都应该绑定到移动/滑动的水平 ListView 的 contentX 属性。请注意,此绑定是动态的:在第一行中滑动时,所有其他行都应绑定到第一行的 contentX。但是在第二行中滑动时应该更改。

关于如何做到这一点的任何建议?

我尝试了一种不同的方法

  • 在垂直 ListView 的顶部创建一个 Flickable Item(contentWidth 是完整的时间窗口)。
  • 将每个水平 ListView 绑定到此 Flickable 的 contentX(这是一个静态绑定)

这导致了很好的同步滚动,但我仍然有一些问题

  • 我不得不做一些技巧来确保轻弹只能是水平或垂直的,而不是两者兼而有之
  • 我无法再点击个别事件;我猜事件被 Flickable 拦截了
  • 我也不确定这种具有巨大 contentWidth 的 Flickable 对内存的影响?

感谢您的反馈!

【问题讨论】:

    标签: qt listview qml qtquick2


    【解决方案1】:

    我会说频道只有一个垂直列表视图。但只有频道名称,而不是实际节目。除了程序的水平视图,您可以将它们全部塞进一个可滑动的内容中,使用开始时间和持续时间通过将它们的 x 和宽度属性绑定到前者来在可滑动的内容中布局程序。

    然后您可以将频道列表视图与节目项的垂直滚动绑定在一起,以便您拥有与相应频道对应的节目。这样,您可以从两者垂直滚动,而只能水平滚动程序。

    这是一个简单的例子:

    ApplicationWindow {
        id: main
        width: 500
        height: 100
        visible: true
        color: "white"
    
        ListModel {
            id: modC
            ListElement { name: "Ch1" }
            ListElement { name: "Ch2" }
            ListElement { name: "Ch3" }
        }
    
        ListModel {
            id: modP1
            ListElement { name: "p1"; start: 0; duration: 6 }
            ListElement { name: "p2"; start: 6; duration: 6 }
            ListElement { name: "p3"; start: 12; duration: 6 }
            ListElement { name: "p4"; start: 18; duration: 6 }
        }
        ListModel {
            id: modP2
            ListElement { name: "p1"; start: 0; duration: 12 }
            ListElement { name: "p2"; start: 12; duration: 12 }
        }
        ListModel {
            id: modP3
            ListElement { name: "p1"; start: 0; duration: 8 }
            ListElement { name: "p2"; start: 8; duration: 8 }
            ListElement { name: "p3"; start: 16; duration: 8 }
        }
    
        property var subMod : [ modP1, modP2, modP3 ]
    
        Component {
            id: progDelegate
            Rectangle {
                property var source
                x: source.start * 50
                width: source.duration * 50
                height: 50
                color: "lightblue"
                border.color: "black"
                Text {
                    text: source.name
                }
            }
        }
    
        Row {
            anchors.fill: parent
            ListView {
                id: list
                height: parent.height
                width: 100
                model: modC
    
                delegate: Item {
                    width: 100
                    height: 50
                    Rectangle {
                        anchors.fill: parent
                        color: "red"
                        border.color: "black"
                        Text {
                            anchors.centerIn: parent
                            text: name
                        }
                    }
                    Component.onCompleted: {
                        var mod = subMod[index]
                        for (var i = 0; i < mod.count; ++i) progDelegate.createObject(flick.contentItem, {"source": mod.get(i), "y": index * 50})
                    }
                }
            }
            Flickable {
                id: flick
                height: parent.height
                width: parent.width - list.width
                contentWidth: 1200
                contentHeight: contentItem.childrenRect.height
                clip: true
                flickableDirection: Flickable.HorizontalFlick
                contentY: list.contentY
            }
        }
    }
    

    【讨论】:

    • 谢谢!很多!但是有两个问题:1)在您的示例中,垂直滚动仅适用于频道列,而不适用于节目区域,而您似乎另有说明(“这样您可以从两者垂直滚动,并且只能水平滚动节目。”) . 2) 知道内容宽度/高度N很大的几乎空的 Flickable 的内存使用情况是什么
    • 1 - 我在写完之前的文本 20 分钟后写了这个例子。在那段时间里,我认为只在频道中进行垂直滚动会更“理智”。您可以进行双向绑定,删除现有的并使用两个视图的onContentYChanged 来同步另一个。 2 - 它不占用任何内存,它是“虚构区域”,只是逻辑,它不像是每个像素都填充的位图。
    • 明白!感谢您帮助我。
    猜你喜欢
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多