研究了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 width: 1280 height: 720 title: qsTr("Hello World") property var fenlei_texts: [ ["KTV热歌","网络歌曲","现场音乐","背景音乐","经典","情歌"], ["夜店","学习工作","咖啡馆","运动","睡前","旅行"], ["伤感","安静","快乐","励志","治愈","思念"], ["00年代","90年代","80年代","70年代"], ["流行","电子","轻音乐","民谣","轻音乐","民谣","说唱","摇滚"], ["英语","韩语","日语","国语"] ] ListModel{ id: phoneModel } Component{ id: sectionHeader Rectangle{ width: parent.width height: childrenRect.height color: "lightsteelblue" Text{ text: section font.bold: true font.pointSize: 20 } } }//sectionHeader is end Component{ id:lisview_gridview Rectangle{ width: 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 width:parent.width
flickDeceleration:0
interactive:false
delegate: Component{ Rectangle{ id:back color:GridView.isCurrentItem?"yellow":"red" //选中颜色设置 height:80 width: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 width: 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 width: 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 width: 158 height: 50 Image{ id: img_return source:"images/button/btn_return/btn_return_n.png" } Text{ x:55 width: 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{ width: parent.width height: 66 color: "transparent" Rectangle{height:27;width: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{ width: 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 width:1280 cellWidth: 300 cellHeight: 140 contentWidth: 0 contentHeight:0 interactive:false delegate: Component{ Rectangle{ id:back color: "#31354d" width: {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 width: 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 width: 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){ fenlei_texts[0][j]=subject_category[j]; } } onScene_category_changed:{ console.log("*****receive********") fenlei_texts[1] = new Array(); for(var j=0;j ){ fenlei_texts[1][j]=scene_category[j]; } } onMood_category_changed:{ console.log("*****receive********") fenlei_texts[2] = new Array(); //声明二维,每一个一维数组里面的一个元素都是一个数组; for(var j=0;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 //一维数组里面每个元素数组可以包含的数量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 //一维数组里面每个元素数组可以包含的数量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 //一维数组里面每个元素数组可以包含的数量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 width: 158 height: 50 Image{ id: img_return source:"images/button/btn_return/btn_return_n.png" } Text{ x:55 width: 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{ width: parent.width height: 66 color: "transparent" Rectangle{height:27;width: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{ width: 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 width:parent.width cellWidth: 300 cellHeight: 140 contentWidth: 0 contentHeight:0 interactive:false delegate: Component{ Rectangle{ id:back color: "#31354d" width: {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 width: 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 } }