概述
Qt中ListView加载数据一般有两种方式,一种是直接qml文件中model直接定义并且放置数据,一种是C++代码中定义Model,再setContextProperty的方式暴露给qml域。
步骤
(1)qml界面
import QtQuick 2.0
import QtQuick.Controls 1.5
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
SubPageForm {title:"切换线路"property int font_mid_size:24bodyArea: Rectangle {id: subrootcolor: "#00ffffff"Image {id: tablebgsource: "../Resources/tablebg.jpg"anchors.left: parent.leftanchors.leftMargin: 50anchors.right: parent.rightanchors.rightMargin: 50anchors.top: parent.topanchors.topMargin: 30ListView {id: datalistanchors.fill: parentinteractive:falseheader:Rectangle{width: datalist.widthheight: 53color:Qt.rgba(0,0,0,0)RowLayout{anchors.left: parent.leftanchors.right: parent.rightheight: parent.heightText{text:"序号"color:"white"font.pixelSize:font_mid_sizehorizontalAlignment: Text.AlignHCenterLayout.fillWidth:true}Text{text:"线路"color:"white"font.pixelSize:font_mid_sizehorizontalAlignment: Text.AlignHCenterLayout.fillWidth:true}Text{text:"方向"color:"white"font.pixelSize:font_mid_sizehorizontalAlignment: Text.AlignHCenterLayout.fillWidth:true}}}delegate:Rectangle{width: datalist.widthheight: 53color:Qt.rgba(0,0,0,0)RowLayout{anchors.left: parent.leftanchors.right: parent.rightheight: parent.heightText{text:PosRolecolor:"white"font.pixelSize:font_mid_sizehorizontalAlignment: Text.AlignHCenterverticalAlignment: Text.AlignVCenterLayout.fillWidth:trueLayout.preferredWidth:100}Text{text:LineRolecolor:"white"font.pixelSize:font_mid_sizehorizontalAlignment: Text.AlignHCenterverticalAlignment: Text.AlignVCenterLayout.fillWidth:trueLayout.preferredWidth:100}Text{text:DirectRolecolor:"white"font.pixelSize:font_mid_sizehorizontalAlignment: Text.AlignHCenterverticalAlignment: Text.AlignVCenterLayout.fillWidth:trueLayout.preferredWidth:100}}}model:LineInfoModel}Component.onCompleted: {LineInfoModel.refresh()}}RowLayout {anchors.left: tablebg.leftanchors.right: tablebg.rightanchors.leftMargin: 10anchors.rightMargin: 10anchors.bottom: parent.bottomanchors.bottomMargin: 10Text {id: footertexttext: qsTr("当前第")+LineInfoModel.curpage+qsTr("页 , 共")+LineInfoModel.totalpage+qsTr("页")+qsTr(" 数量")+LineInfoModel.linenumLayout.preferredHeight: 42Layout.preferredWidth: 560font.pixelSize: font_mid_sizecolor:"white"}NormalButton {id: previouspageLayout.preferredHeight: 35Layout.preferredWidth: 35imgsource:pressed? "qrc:/Resources/up_click.bmp":"qrc:/Resources/up.bmp"onClicked: {LineInfoModel.jumptoPrevious();}}NormalButton {id: nextpageLayout.preferredHeight: 35Layout.preferredWidth: 35imgsource: pressed? "qrc:/Resources/down_click.bmp":"qrc:/Resources/down.bmp"onClicked: {LineInfoModel.jumptoNext();}}}}}
(2)自定义Model类(继承QAbstractListModel)
#ifndef LINEINFOMODEL_H
#define LINEINFOMODEL_H#include<QAbstractListModel>
class Line_Element
{
public:Line_Element(int pos,QString line ,QString direct){m_pos = pos;m_line = line;m_direct = direct;}int getPos()const{ return m_pos;}QString getLine() const{return m_line;}QString getDirect() const{return m_direct;}
private:int m_pos;QString m_line;QString m_direct;
};class LineInfoModel : public QAbstractListModel
{Q_PROPERTY(int curpage READ getCurpage WRITE setCurpage NOTIFY curpageChanged)Q_PROPERTY(int totalpage READ getTotalpage WRITE setTotalpage NOTIFY totalpageChanged)Q_PROPERTY(int linenum READ getLineNum WRITE setLineNum NOTIFY linenumChanged)Q_OBJECT
public:LineInfoModel();enum LineInfo_Roles{PosRole =Qt::UserRole + 1,LineRole,DirectRole};int rowCount(const QModelIndex & parent = QModelIndex()) const;QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;QHash<int, QByteArray> roleNames() const;void addLine(int pos,QString line,QString direct);void setLines(const QList<Line_Element>& list);int getCurpage(){return m_curpage;}void setCurpage(int val){m_curpage = val; emit curpageChanged();}int getTotalpage(){return m_totalpage;}void setTotalpage(int val){m_totalpage = val;emit totalpageChanged();}int getLineNum(){return m_linenum;}void setLineNum(int val){m_linenum = val;emit linenumChanged();}void RefreshDisplay();
public slots:void jumptoPrevious();void jumptoNext();void refresh(){RefreshDisplay();};
signals:void curpageChanged();void totalpageChanged();void linenumChanged();
private:QList<Line_Element> m_display_list;QList<Line_Element> m_line_list;int m_curpage = 0;int m_totalpage = 0;int m_linenum = 0;//amount of lines
};#endif // LINEINFOMODEL_H
#include "LineInfoModel.h"
#include<QDebug>
LineInfoModel::LineInfoModel()
{m_curpage=0;m_totalpage=0;m_linenum=0;
}/*** @brief LineInfoModel::addLine 添加一条数据* @param pos* @param line* @param direct*/
void LineInfoModel::addLine(int pos, QString line, QString direct)
{Line_Element ele(pos,line,direct);m_line_list.append(ele);int _line_num = m_line_list.count();setCurpage(1);setTotalpage(_line_num/5+1);setLineNum(_line_num);
}
/*** @brief LineInfoModel::setLines 设置 List* @param list*/
void LineInfoModel::setLines(const QList<Line_Element> &list)
{m_line_list.clear();m_line_list = list;int _line_num = m_line_list.count();qDebug()<<"line num = "<<_line_num;if(_line_num>0){setCurpage(1);setTotalpage(_line_num/5+1);setLineNum(_line_num);m_display_list.clear();for(int i=0;i<m_line_list.count();i++){m_display_list<<m_line_list.at(i);}}
}/*** @brief LineInfoModel::jumptoPrevious 上一页*/
void LineInfoModel::jumptoPrevious()
{if(m_curpage<=1){return;}setCurpage(m_curpage-1);RefreshDisplay();
}/*** @brief LineInfoModel::jumptoNext 下一页*/
void LineInfoModel::jumptoNext()
{if(m_curpage>=m_totalpage){return;}setCurpage(m_curpage+1);RefreshDisplay();
}/*** @brief LineInfoModel::RefreshDisplay 刷新页面*/
void LineInfoModel::RefreshDisplay()
{beginRemoveRows(QModelIndex(),0,m_display_list.count());m_display_list.clear();endRemoveRows();int num=0;if(m_curpage<m_totalpage){num=5;}else{num = m_linenum%5;}beginInsertRows(QModelIndex(),0,num);for(int i=0;i<num;i++){int _index = (m_curpage-1)*5+i;m_display_list<<m_line_list.at(_index);}endInsertRows();
}/*** @brief LineInfoModel::roleNames 返回模型的属性名称。继承自父类。* @return*/
QHash<int, QByteArray> LineInfoModel::roleNames() const
{QHash<int, QByteArray> roles;roles[PosRole] = "PosRole";roles[LineRole] = "LineRole";roles[DirectRole]= "DirectRole";return roles;
}/*** @brief LineInfoModel::rowCount 返回模型的行数,此函数会在需要指导模型行数的时候被自动调用* @param parent* @return*/
int LineInfoModel::rowCount(const QModelIndex &parent) const
{return m_display_list.count();
}/*** @brief LineInfoModel::data 返回数据* @param index 需要的数据的序号* @param role 需要的数据的角色* @return*/
QVariant LineInfoModel::data(const QModelIndex &index, int role) const
{Line_Element ele = m_display_list.at(index.row());switch(role){case PosRole:{return ele.getPos();}case LineRole:{return ele.getLine();}case DirectRole:{return ele.getDirect();}}
}
这里主要实现三个方法:
<1>int rowCount(const QModelIndex & parent = QModelIndex()) const;
<2>QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
<3>QHash< int, QByteArray> roleNames() const;
(3)暴露自定义Model给qml域
context->setContextProperty("LineInfoModel",&msg.m_lineinfo_model);
上下文属性可以存储为QVariant或者QObject*类型.这意味着自定义的C++对象也可以使用这种方式注入,而且可以直接在QML中读取或修改这些对象.我们将上例中的QDateTime值修改为一个嵌入的QObject实例,让QML代码调用对象实例的方法