在QML中具有嵌套滚动区域的二维表

时间:2015-04-17 13:40:54

标签: qt listview qml qtquick2

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

之类的东西

http://zappware.com/wbdsgn/wp-content/uploads/2014/08/Zuku_v03_EPG_01_Caslte.jpg

最初,我创建了

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

到目前为止一切顺利。唯一的缺点是水平ListViews一个接一个地滚动,同时它们应该一起滚动。

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

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

我尝试了一种不同的方法

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

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

  • 我必须做一些技巧,以确保轻弹只是水平或垂直,但不是两个
  • 我再也无法点击个别活动了;我想事件被Flickable拦截了
  • 我也不确定这样一个具有巨大contentWidth的Flickable的内存影响?

反馈意见!

1 个答案:

答案 0 :(得分:3)

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

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

这是一个简单的例子:

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
        }
    }
}