自定义 QAbstractTableModel,用于QML的TableView或者 QTableView

牛景同
2023-12-01

自定义 QAbstractTableModel

mytablemodel.h

#ifndef MYTABLEMODEL_H
#define MYTABLEMODEL_H

#include <QAbstractTableModel>
#include <QObject>

class MyTableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    MyTableModel(QObject *parent = nullptr);
    ~MyTableModel();

    ///设置表头数据
    void SetHeadData(const QStringList& list);
    ///设置表格数据
    void SetData(const QMap<int, QVector<QString>>& map);

public:
    ///返回行数
    int rowCount(const QModelIndex& parent) const override;
    ///返回列数
    int columnCount(const QModelIndex& parent) const override;
    ///返回索引数据
    QVariant data(const QModelIndex& index, int role) const override;
    ///返回指定表头数据
    QVariant headerData(int section, Qt::Orientation orientation, int role) const override;

    /// qml delegate 访问的名称
    QHash<int, QByteArray> roleNames() const override;

private:
    //表头数据
    QStringList m_headData;
    //显示的数据
    QMap<int, QVector<QString>> m_datas;
};

#endif // MYTABLEMODEL_H

mytablemodel.cpp

#include "mytablemodel.h"

#include <QDebug>


MyTableModel::MyTableModel(QObject *parent)
{


}

MyTableModel::~MyTableModel()
{

}

void MyTableModel::SetHeadData(const QStringList &list)
{
    m_headData = list;
}

void MyTableModel::SetData(const QMap<int, QVector<QString> > &map)
{
    beginResetModel();  //刷新表格
    m_datas = map;
    endResetModel();
}

int MyTableModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid()) {
        return 0;
    } else {
        return m_datas.size();  //显示数据的大小
    }
}

int MyTableModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid()) {
          return 0;
      } else {
          return m_headData.size();   //表头的大小
    }
}

QVariant MyTableModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }
    if (role == Qt::DisplayRole) {
        return (m_datas.begin() + index.row())->at(index.column()); //单元格中数据
    }
    if (role == Qt::TextAlignmentRole) {    //对其方式
        return Qt::AlignCenter; //对齐格式为居中
    }
    return QVariant();
}

QVariant MyTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal) {    //水平表头
           if (role == Qt::DisplayRole) {  //角色为显示
               return m_headData.at(section);  //返回指定位置表头
           }
       }
       return QAbstractTableModel::headerData(section, orientation, role);
}

QHash<int, QByteArray> MyTableModel::roleNames() const
{
    return { {Qt::DisplayRole, "display"} };
}

ModuleManager,槽函数接收数据,刷新model

ModuleManager::ModuleManager(QQmlContext*contxt,QObject *parent)
    ,m_rawTableModel(new MyTableModel(this))
    ,m_trackTableModel(new MyTableModel(this))
    {
    }
    
void ModuleManager::registerQml()
{
    m_context->setContextProperty("_ModuleManager",this);
    m_context->setContextProperty("_RawTableModel",m_rawTableModel);
    m_context->setContextProperty("_TrackTableModel",m_trackTableModel);
}

// sDetectList 是自定义结构体,这里是举例,可以用其它自定义结构体代替
void ModuleManager::onDetectListChanged(sDetectList detlist)
{
    GlobalData::getInstance()->insertIdRawMap(detlist.radarId,detlist);

    //update model
    QMap<int, QVector<QString>> map;
    for(int i=0;i<detlist.num_detectObjs;i++)
    {

        QVector<QString> vec;
        vec.push_back(QString::number(detlist.detectObjs[i].usMeaID));
        vec.push_back(QString::number(detlist.detectObjs[i].usRange*INV_ONE6_SCALE));
        vec.push_back(QString::number(detlist.detectObjs[i].ssVelocity*INV_ONE6_SCALE));
        vec.push_back(QString::number(detlist.detectObjs[i].ssAzimuth*INV_ONE6_SCALE));
        vec.push_back(QString::number(detlist.detectObjs[i].ssHeight*INV_ONE6_SCALE));

        map.insert(i, vec);
    }
    m_rawTableModel->SetData(map);

    //update vqml iew
    //QQmlApplicationEngine *eng =  qobject_cast<QQmlApplicationEngine*>(m_context->engine());
    //TAViewQuick *taview =eng->rootObjects().at(0)->findChild<TAViewQuick *>("ObjTAView");
    //taview->update();


}
// sTrackList 是自定义结构体,这里是举例,可以用其它自定义结构体代替
void ModuleManager::onTrackListChanged(sTrackList tracklist)
{
    GlobalData::getInstance()->insertIdTrackMap(tracklist.radarId,tracklist);


    //update model
    QMap<int, QVector<QString>> map;
    for(int i=0;i<tracklist.num_trackObjs;i++)
    {

        QVector<QString> vec;
        vec.push_back(QString::number(tracklist.trackObjs[i].uiTrackID));
        vec.push_back(QString::number(tracklist.trackObjs[i].traj.x*INV_ONE6_SCALE));
        vec.push_back(QString::number(tracklist.trackObjs[i].traj.y*INV_ONE6_SCALE));
        vec.push_back(QString::number(tracklist.trackObjs[i].traj.vx*INV_ONE6_SCALE));
        vec.push_back(QString::number(tracklist.trackObjs[i].traj.vy*INV_ONE6_SCALE));

        map.insert(i, vec);
    }
    m_trackTableModel->SetData(map);

    //update qml view
    //QQmlApplicationEngine *eng =  qobject_cast<QQmlApplicationEngine*>(m_context->engine());
    //TAViewQuick *taview =eng->rootObjects().at(0)->findChild<TAViewQuick *>("ObjTAView");
    t//aview->update();
}

qml TableView 使用

MyPanelItem.qml 组件

import QtQml 2.12
import QtQuick 2.12
import QtQuick.Controls 2.12

import QtQuick.Layouts 1.12

import Com.Base.UI 1.0


Item {
    id:root

    property alias tableModel  : tableView.model
    property int contentWidth:100
    onContentWidthChanged: {
         forceLayout()
    }

    function forceLayout()
    {
        tableView.forceLayout()
    }

    //列头部
    Row {
        id: columnsHeader
        anchors{
            fill:parent
            bottomMargin: tableView.contentY
        }

        spacing: 1
        Repeater {
            anchors.fill: parent
            model: tableView.columns > 0 ? tableView.columns : 1
            Rectangle{
                clip: true
                width: contentWidth/tableView.columns
                height: 30
                color: "#ababab"
                Text {
                    id:info
                    color: "#121212"
                    //表头
                    text: tableModel.headerData(modelData, Qt.Horizontal)
                    horizontalAlignment:Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                    font{
                        pixelSize: 20
                    }
                }
            }
        }
    }

    TableView{//表
        id:tableView
        anchors{
            topMargin: 30
            fill: parent
        }

        flickDeceleration:Flickable.VerticalFlick

        columnSpacing: 1
        rowSpacing: 1
        clip: true
        delegate :  Rectangle {
            color: "#999999"
            implicitWidth: contentWidth/tableView.columns
            implicitHeight: 20
            Text {
                //这里是 MyTableModel::roleNames() 
                text:display
                color: "#121212"
                verticalAlignment: Text.AlignVCenter
                font{
                    pixelSize: 20
                }
            }
        }
    }

}

MyPanel.qml

import QtQml 2.12
import QtQuick 2.12
import QtQuick.Controls 2.12

import QtQuick.Layouts 1.12

import Com.Base.UI 1.0

Item {
    id:root
    implicitHeight: 200
    implicitWidth: 100

    //动态分隔
    property var spliterPosPencent: 0.3
    property var spliterPos : spliterPosPencent * root.height



    property int panelContentWidth : 100
    onPanelContentWidthChanged: {
        forceLayout()
    }
    function forceLayout()
    {
        rawPanel.forceLayout()
        trackPanel.forceLayout()
    }



    MyPanelItem{
        id:rawPanel
        anchors{
            top:parent.top
            left: parent.left
            right: parent.right
            bottom: spliterRec.top
        }

        tableModel:_RawTableModel
        contentWidth: panelContentWidth
    }
    MyPanelItem{
        id:trackPanel
        anchors{
            top:spliterRec.bottom
            left: parent.left
            right: parent.right
            bottom: parent.bottom
        }
        tableModel:_TrackTableModel
        contentWidth: panelContentWidth
    }

    Rectangle{//spliter
        id:spliterRec
        y:spliterPos
        height:2
        width: parent.width
        color: "red"
        MouseArea {
           id: dragArea
           hoverEnabled:true

           cursorShape:containsMouse?Qt.OpenHandCursor:Qt.ArrowCursor

           anchors.fill: parent

           drag.target: parent
           drag.axis:Drag.YAxis
           drag.minimumY: 50
           drag.maximumY: root.height - 50
           onMouseXChanged: {
               spliterPosPencent = spliterRec.y/root.height
               spliterPos = spliterPosPencent * root.height
           }

        }
    }

    onHeightChanged: {
        console.log(height,spliterPosPencent)
        spliterPos = spliterPosPencent*root.height
        forceLayout()
    }


}
 类似资料: