qml lisrview嵌套GridView

研究了2天时间,网上连个例子都没找到。这几天都失眠了!也没有大神指点下。。。我不想做这个了

list自带title效果,因此。如果想实现带title的网格布局时,只能仿照安卓的思路,listview嵌套gridview

代码如下:

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3


Window {
    visible: true
     1280
    height: 720
    title: qsTr("Hello World")

    property var fenlei_texts:
              [
                  ["KTV热歌","网络歌曲","现场音乐","背景音乐","经典","情歌"],
                  ["夜店","学习工作","咖啡馆","运动","睡前","旅行"],
                  ["伤感","安静","快乐","励志","治愈","思念"],
                  ["00年代","90年代","80年代","70年代"],
                  ["流行","电子","轻音乐","民谣","轻音乐","民谣","说唱","摇滚"],
                  ["英语","韩语","日语","国语"]
            ]
            ListModel{
                id: phoneModel
            }
            Component{
                id: sectionHeader

                Rectangle{
                     parent.width
                    height: childrenRect.height
                    color: "lightsteelblue"
                    Text{
                        text: section
                        font.bold: true
                        font.pointSize: 20
                    }
                }
            }//sectionHeader is end

        Component{
            id:lisview_gridview
            Rectangle{

             ListView.view.width
            height: 80
            color: ListView.isCurrentItem?"#157efb":"#53d769" //选中颜色设置
            border.color: Qt.lighter(color, 1.1)
            GridView{
                id:grid_view
                model:fenlei_texts[index%6]
                height:parent.height
                parent.width
         flickDeceleration:0
interactive:false
delegate: Component{ Rectangle{ id:back color:GridView.isCurrentItem?"yellow":"red" //选中颜色设置 height:80 80 Text{ anchors.centerIn: parent text:modelData } MouseArea { anchors.fill: parent acceptedButtons: Qt.AllButtons onClicked:{ grid_view.currentIndex = index //实现item切换 console.log("*******grid_currentIndex**********"+index) } onPressed: {back.color = "yellow"} onReleased: {back.color = "red"} } } } Component.onCompleted: { grid_view.currentIndex = -1; } } MouseArea { anchors.fill: parent propagateComposedEvents: true onPressed:{ listview.currentIndex = index //实现item切换 grid_view.currentIndex = -1 mouse.accepted = false console.log("*******List_currentIndex**********"+index) } } } } ListView { id:listview  parent.width height: parent.height model:phoneModel clip:true delegate:lisview_gridview section.property: "manufacture" section.criteria: ViewSection.FullString section.delegate: sectionHeader } Component.onCompleted: { phoneModel.append({"manufacture":"主题"}) phoneModel.append({"manufacture":"场景"}) phoneModel.append({"manufacture":"心情"}) phoneModel.append({"manufacture":"年代"}) phoneModel.append({"manufacture":"流派"}) phoneModel.append({"manufacture":"语种"}) } }

鼠标穿透是qml永远绕不过的梗呀!我差点都放弃了。

总共有几个难点:

1)首先是布局,动态加载的数据-model,使得后台能够出现直接加载成model,对view进行数据的赋值

2)主题,场景,心情,年代,流派,语种是listview

而主题下的分类却是gridview,怎么区分一横一纵的索引,以二维数组的形式获得。把获得索引,传给后台。后端能够根据索引,取得id,从而继续请求数据

3)鼠标穿透,由于qml自己的坑,多重mousearea,导致下层的mousearea永远无法响应pressed事件,那么小分类就没有点击态。从用户的效果,就不知道点击了没有。

当MouseArea响应事件顺序都是press>release>click

仍然未解决问题:

1)Gridview,listview具有滑动效果,对于体验不太好。

2)如果光标在一瞬间离开Gridview或者Listview,button的压下态无法复原。这个是QT共同问题。

效果图:

import QtQuick 2.0
import QtQuick.Controls 2.3

Item {
    id:layout_recommend_list
     1280
    height: 720
    visible: true
    property var fenlei_texts:
                  [
                      ["KTV热歌","网络歌曲","现场音乐","背景音乐","经典","情歌"],
                      ["夜店","学习工作","咖啡馆","运动","睡前","旅行","夜店"],
                      ["伤感","安静","快乐","励志","治愈"],
                      ["00年代","90年代","80年代","70年代","思念"],
                      ["流行","电子","轻音乐","民谣","轻音乐","民谣","说唱","摇滚"],
                      ["英语","韩语","日语","国语"]
                ]
    Image{
        id:back_img
        source: "images/background/bg_music.png"
        visible:true
    }
    MouseArea{
        anchors.fill:parent
        enabled:true
        onClicked: {}
        onPressed: {}
        onReleased: {}
    }
    Item{
        id:item_song_sheet
        visible:true

        Item{
            x:14
            y:73
             158
            height: 50

            Image{
                id: img_return
                source:"images/button/btn_return/btn_return_n.png"
            }

            Text{
                x:55
                 103
                height: parent.height
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignLeft
                text: qsTr("全部分类")
                font.pixelSize: 26
                font.family: "FZLTHJW--GB1-0"
                color: "#ffffff"
            }

            MouseArea{
                anchors.fill: parent
                onClicked: {
                    if (stack.depth === 1)
                    {
                        stack.clear();
                    }
                    else
                    {
                        stack.pop();
                    }
                }
                onPressed: {
                    img_return.source = "images/button/btn_return/btn_return_p.png"
                }
                onReleased: {
                    img_return.source = "images/button/btn_return/btn_return_n.png"
                }
            }
        }
    }
                ListModel{
                    id: phoneModel
                }
                Component{
                    id: sectionHeader

                    Rectangle{
                         parent.width
                        height: 66
                        color: "transparent"
                        Rectangle{height:27;4;color: "#3cecc8"}
                        Text{
                            anchors.left:parent.left
                            anchors.leftMargin: 19
                            anchors.top:parent.top
                            text: section
                            font.pixelSize: 26
                            color: "#ffffff"
                            font.family: "FZLTHJW--GB1-0"   //字体
                            opacity: 0.9
                        }
                    }
                }//sectionHeader is end
            function calculate_height(count)
            {
                console.log("*******count:**********",count)
                var divisor_count;
                var remainder_count;
                var divisor_height;
                var n
                divisor_count = Math.floor(count/4);
                remainder_count = count%4;
                if(divisor_count === 0)
                {n =1}
                else if(divisor_count >= 1)
                {
                    if(remainder_count === 0)
                    {
                         n = divisor_count;
                    }
                    else
                    {
                        n = divisor_count + 1;
                    }
                }
                console.log("*******n:**********",n)
                divisor_height = 152 + (n -1)*140;
                console.log("*******divisor_height:**********",divisor_height)

                return divisor_height;
            }
            Component{
                id:lisview_gridview
                Rectangle{

                 ListView.view.width
                height: calculate_height(fenlei_texts[index%6].length)
                color: "transparent"
                border.color: Qt.lighter(color, 1.1)
                GridView{
                    id:grid_view
                    property int spacing: 40
                    model:fenlei_texts[index%6]
                    height:parent.height
                    1280
                    cellWidth: 300
                    cellHeight: 140
                    contentWidth: 0
                    contentHeight:0
                    interactive:false
                    delegate: Component{
                        Rectangle{
                            id:back
                            color: "#31354d"
                             {grid_view.cellWidth - grid_view.spacing}
                            height: {grid_view.cellHeight - grid_view.spacing}
                            Text{
                                anchors.centerIn: parent
                                text:modelData
                                font.pixelSize: 26
                                color: "#ffffff"
                                font.family: "FZLTHJW--GB1-0"   //字体
                                opacity: 0.9
                            }
                            MouseArea {
                            anchors.fill: parent
                            acceptedButtons: Qt.AllButtons
                            onClicked:{
                                grid_view.currentIndex = index  //实现item切换
                                console.log("*******grid_currentIndex**********"+index)
                                }
                            onPressed: {back.opacity = 0.3}
                            onReleased: {back.opacity = 1}
                            }

                        }
                    }
                    Component.onCompleted: {
                        grid_view.currentIndex = -1;
                    }

                }
                    MouseArea {
                    anchors.fill: parent
                    propagateComposedEvents: true
                    onPressed:{
                        listview.currentIndex = index  //实现item切换
                        grid_view.currentIndex = -1
                        mouse.accepted = false
                        console.log("*******List_currentIndex**********"+index)
                        }
                    }
                }
            }
            ListView {
                id:listview
                x:60
                y:152
                 parent.width
                height: 466
                model:phoneModel
                delegate:lisview_gridview
                section.property: "manufacture"
                section.criteria: ViewSection.FullString
                section.delegate: sectionHeader
                clip: true
            }
            Component.onCompleted: {
                phoneModel.append({"manufacture":"主题"})
                phoneModel.append({"manufacture":"场景"})
                phoneModel.append({"manufacture":"心情"})
                phoneModel.append({"manufacture":"年代"})
                phoneModel.append({"manufacture":"流派"})
                phoneModel.append({"manufacture":"语种"})

            }
}

 1)Gridview,listview具有滑动效果,对于体验不太好。-->此问题解决 ,将Gridview的interactive置为false.

如果有剪切效果,就把clip:true

如果是从后台给的数据的话,想要动态实现二维数据,需要使用运用js拼出数据。现在需要的数据是数组套数组。比如tarray[onearray[],twoarray[],threearrap[]].

import QtQuick 2.0
import QtQuick.Controls 2.3

Item {
    id:layout_recommend_list
     1280
    height: 720
    visible: true
    property int i: 0
    Component.onCompleted: {
        console.log("*****complete********")
        qml_log_observer.request_info()
    }
    property var fenlei_texts:new Array

    Image{
        id:back_img
        source: "images/background/bg_music.png"
        visible:true
    }
    Connections{
        target: qml_log_observer
        onCategories_titles_changed:{
            for(i = 0;i < titles.length;++i)
            {
                console.log("*****receive_Categories********")
                phoneModel.append({"manufacture":titles[i]})
            }
        }
        onSubject_category_changed:{
            console.log("*****receive********")
                fenlei_texts[0] = new Array();
                for(var j=0;j<subject_category.length;j++){
                    fenlei_texts[0][j]=subject_category[j];
                    }
            }
        onScene_category_changed:{
            console.log("*****receive********")
                fenlei_texts[1] = new Array();
                for(var j=0;j<scene_category.length;j++){
                    fenlei_texts[1][j]=scene_category[j];
                    }
        }
        onMood_category_changed:{
            console.log("*****receive********")
                fenlei_texts[2] = new Array(); //声明二维,每一个一维数组里面的一个元素都是一个数组;
                for(var j=0;j<mood_category.length;j++){ //一维数组里面每个元素数组可以包含的数量p,p也是一个变量;
                    fenlei_texts[2][j]=mood_category[j]; //这里将变量初始化,我这边统一初始化为空,后面在用所需的值覆盖里面的值
                    }
        }
        onAge_category_changed:{
            console.log("*****receive********")
                fenlei_texts[3] = new Array(); //声明二维,每一个一维数组里面的一个元素都是一个数组;
                for(var j=0;j<age_category.length;j++){ //一维数组里面每个元素数组可以包含的数量p,p也是一个变量;
                    fenlei_texts[3][j]=age_category[j]; //这里将变量初始化,我这边统一初始化为空,后面在用所需的值覆盖里面的值
                    }
        }
        onGenre_category_changed:{
            console.log("*****receive********")
                fenlei_texts[4] = new Array(); //声明二维,每一个一维数组里面的一个元素都是一个数组;
                for(var j=0;j<genre_category.length;j++){ //一维数组里面每个元素数组可以包含的数量p,p也是一个变量;
                    fenlei_texts[4][j]=genre_category[j]; //这里将变量初始化,我这边统一初始化为空,后面在用所需的值覆盖里面的值
                    }
        }
        onLanguage_category_changed:{
            console.log("*****receive********")
                fenlei_texts[5] = new Array(); //声明二维,每一个一维数组里面的一个元素都是一个数组;
                for(var j=0;j<language_category.length;j++){ //一维数组里面每个元素数组可以包含的数量p,p也是一个变量;
                    fenlei_texts[5][j]=language_category[j]; //这里将变量初始化,我这边统一初始化为空,后面在用所需的值覆盖里面的值
                    }
        }
    }
    MouseArea{
        anchors.fill:parent
        enabled:true
        onClicked: {}
        onPressed: {}
        onReleased: {}
    }
    Item{
        id:item_song_sheet
        visible:true

        Item{
            x:14
            y:73
             158
            height: 50

            Image{
                id: img_return
                source:"images/button/btn_return/btn_return_n.png"
            }

            Text{
                x:55
                 103
                height: parent.height
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignLeft
                text: qsTr("全部分类")
                font.pixelSize: 26
                font.family: "FZLTHJW--GB1-0"
                color: "#ffffff"
            }

            MouseArea{
                anchors.fill: parent
                onClicked: {
                    if (stack.depth === 1)
                    {
                        stack.clear();
                    }
                    else
                    {
                        stack.pop();
                    }
                }
                onPressed: {
                    img_return.source = "images/button/btn_return/btn_return_p.png"
                }
                onReleased: {
                    img_return.source = "images/button/btn_return/btn_return_n.png"
                }
            }
        }
    }
                ListModel{
                    id: phoneModel
                }
                Component{
                    id: sectionHeader

                    Rectangle{
                         parent.width
                        height: 66
                        color: "transparent"
                        Rectangle{height:27;4;color: "#3cecc8"}
                        Text{
                            anchors.left:parent.left
                            anchors.leftMargin: 19
                            anchors.top:parent.top
                            text: section
                            font.pixelSize: 26
                            color: "#ffffff"
                            font.family: "FZLTHJW--GB1-0"   //字体
                            opacity: 0.9
                        }
                    }
                }//sectionHeader is end
            function calculate_height(count)
            {
                console.log("*******count:**********",count)
                var divisor_count;
                var remainder_count;
                var divisor_height;
                var n
                divisor_count = Math.floor(count/4);
                remainder_count = count%4;
                if(divisor_count === 0)
                {n =1}
                else if(divisor_count >= 1)
                {
                    if(remainder_count === 0)
                    {
                         n = divisor_count;
                    }
                    else
                    {
                        n = divisor_count + 1;
                    }
                }
                console.log("*******n:**********",n)
                divisor_height = 152 + (n -1)*140;
                console.log("*******divisor_height:**********",divisor_height)

                return divisor_height;
            }
            Component{
                id:lisview_gridview
                Rectangle{

                 ListView.view.width
                height: calculate_height(fenlei_texts[index%6].length)
                color: "transparent"
                border.color: Qt.lighter(color, 1.1)
                GridView{
                    id:grid_view
                    property int spacing: 40
                    model:fenlei_texts[index%6]
                    height:parent.height
                    parent.width
                    cellWidth: 300
                    cellHeight: 140
                    contentWidth: 0
                    contentHeight:0
                    interactive:false
                    delegate: Component{
                        Rectangle{
                            id:back
                            color: "#31354d"
                             {grid_view.cellWidth - grid_view.spacing}
                            height: {grid_view.cellHeight - grid_view.spacing}
                            visible: grid_text.text === ""?0:1
                            Text{
                                id:grid_text
                                anchors.centerIn: parent
                                text:modelData
                                font.pixelSize: 26
                                color: "#ffffff"
                                font.family: "FZLTHJW--GB1-0"   //字体
                                opacity: 0.9
                                visible: grid_text.text === ""?0:1
                            }
                            MouseArea {
                            anchors.fill: parent
                            acceptedButtons: Qt.AllButtons
                            onClicked:{
                                grid_view.currentIndex = index  //实现item切换
                                console.log("*******grid_currentIndex**********"+index)
                                }
                            onPressed: {back.opacity = 0.3}
                            onReleased: {back.opacity = 1}
                            }

                        }
                    }
                    Component.onCompleted: {
                        grid_view.currentIndex = -1;
                    }

                }
                    MouseArea {
                    anchors.fill: parent
                    propagateComposedEvents: true
                    onPressed:{
                        listview.currentIndex = index  //实现item切换
                        grid_view.currentIndex = -1
                        mouse.accepted = false
                        console.log("*******List_currentIndex**********"+index)
                        }
                    }
                }
            }
            ListView {
                id:listview
                x:60
                y:152
                 parent.width
                height: 466
                model:phoneModel
                delegate:lisview_gridview
                section.property: "manufacture"
                section.criteria: ViewSection.FullString
                section.delegate: sectionHeader
                clip: true
            }
            Component.onDestruction: {
                fenlei_texts.length = 0
            }
}
原文地址:https://www.cnblogs.com/wxmwanggood/p/11024034.html