qt的model view 使用示范

首先在ui界面拖一个tableView

ui->tableView->setModel(mission_model);

然后设置model的qss,并用view绑定model

void SettingWidget::init_missionmodel(QString plane_type, QString mission_name)
{
    if(mission_model)
        delete mission_model;
    mission_model = new MissionModel(plane_type, mission_name, this);
    connect(mission_model, SIGNAL(missionFollow_send(QVariant, QVariant)), this, SLOT(getMissionFollow(QVariant, QVariant)));
    connect(mission_model, SIGNAL(namePlate_show(QVariant)), this, SLOT(getNamePlate(QVariant)));
    ui->tableView->setModel(mission_model);
    int row_count = mission_model->rowCount();
    for (int i = 0; i < row_count; i++)
    {
        QModelIndex index = mission_model->index(i, 4);
        QPushButton *button = static_cast<QPushButton*>(index.internalPointer());
        ui->tableView->setIndexWidget(index, button);
    }

    ui->tableView->horizontalHeader()->resizeSection(0,80);
    ui->tableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);
    ui->tableView->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Stretch);

    //ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
    ui->tableView->verticalHeader()->hide();
  //  ui->tableView->horizontalHeader()->setStyleSheet("QHeaderView::section{background:#3a3e46;color: white;}");
}

MissionModel.h

#ifndef MISSIONMODEL_H
#define MISSIONMODEL_H

#include <QAbstractTableModel>
#include <QJsonObject>
#include <QJsonArray>
#include <QPushButton>
#include <QMap>


class MissionModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    MissionModel(QString plane_name_t, QString mission_name, QObject *parent = nullptr);
    virtual ~MissionModel() override;

    // Header:
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;

    // Basic functionality:
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;

    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

    bool setData(const QModelIndex &index, const QVariant &value, int role) override;

    void refresh();

    Qt::ItemFlags flags(const QModelIndex & index) const override ;

    QJsonObject getItemData(int index);

    void init_data();

signals:
    void missionFollow_send(QVariant missionName, QVariant missionColor);
    void namePlate_show(QVariant missionName);

private:
    QList<QString> headtitle;
    QJsonArray dataList;

    QMap<int,QPushButton* > color_buttons;

    QString plane_name;
    QString mission_name;
    QString file_name;
};

#endif // MISSIONMODEL_H

MissionModel.cpp

#include "missionmodel.h"

#include <QCoreApplication>
#include <QFile>
#include <QJsonArray>
#include <QMessageBox>
#include <QColorDialog>

#include "global.h"
#include "./ui/util/jsontool.h"

MissionModel::MissionModel(QString plane_name_t, QString mission_name_t, QObject *parent)
    : plane_name(plane_name_t), mission_name(mission_name_t), QAbstractTableModel(parent)
{
    headtitle<< QStringLiteral("序号") << QStringLiteral("项目名称") << QStringLiteral("实时关注") << QStringLiteral("铭牌显示") << QStringLiteral("颜色");

    init_data();
}

MissionModel::~MissionModel()
{
    foreach (QPushButton* button, color_buttons.values()) {
        delete button;
    }
    color_buttons.clear();
}

QVariant MissionModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    switch(role){
    case Qt::DisplayRole:
    {
        if (orientation == Qt::Horizontal) {
            return headtitle[section];
        }
        break;
    }
//    case Qt::FontRole:
//    {
//        QFont boldFont;
//        boldFont.setBold(true);
//        boldFont.setPixelSize(14);
//        return boldFont;
//    }
    case Qt::TextAlignmentRole:
        return Qt::AlignLeft + Qt::AlignVCenter;
        break;
    }
    return QVariant();
}

int MissionModel::rowCount(const QModelIndex &parent) const
{
    return dataList.size();
}

int MissionModel::columnCount(const QModelIndex &parent) const
{
    return headtitle.size();
}


//在第4列放按钮
QModelIndex MissionModel::index(int row, int column, const QModelIndex &parent) const
{

    if (column == 4)
    {
        return createIndex(row, column, color_buttons[row]);
    }
    else
        return QAbstractTableModel::index(row, column, parent);
}
//在第 2,3 列放checkbox
Qt::ItemFlags MissionModel::flags(const QModelIndex &index) const
{
    if (index.column() == 2 || index.column() == 3)
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;

    return QAbstractTableModel::flags(index);
}

//这里负责把数据显示到界面对应单元格
重点
setdata()的调用次数=row * col *31(枚举数)

有多少行就调用多少次。每一行有多少列就调用多少次。对每一个单元格的枚举调用多少次

如下图针对每个单元格的31哥枚举会调用31次data()
比如背景颜色,文本居中,文本颜色,显示内容,如果是checkbox,那么选中状态bool

 Qt::TextAlignmentRole: Qt::DisplayRole: Qt::CheckStateRole:
  enum ItemDataRole {
        DisplayRole = 0,
        DecorationRole = 1,
        EditRole = 2,
        ToolTipRole = 3,
        StatusTipRole = 4,
        WhatsThisRole = 5,
        // Metadata
        FontRole = 6,
        TextAlignmentRole = 7,
        BackgroundRole = 8,
        ForegroundRole = 9,
#if QT_DEPRECATED_SINCE(5, 13) // ### Qt 6: remove me
        BackgroundColorRole Q_DECL_ENUMERATOR_DEPRECATED = BackgroundRole,
        TextColorRole Q_DECL_ENUMERATOR_DEPRECATED = ForegroundRole,
#endif
        CheckStateRole = 10,
        // Accessibility
        AccessibleTextRole = 11,
        AccessibleDescriptionRole = 12,
        // More general purpose
        SizeHintRole = 13,
        InitialSortOrderRole = 14,
        // Internal UiLib roles. Start worrying when public roles go that high.
        DisplayPropertyRole = 27,
        DecorationPropertyRole = 28,
        ToolTipPropertyRole = 29,
        StatusTipPropertyRole = 30,
        WhatsThisPropertyRole = 31,
        // Reserved
        UserRole = 0x0100
    };

QVariant MissionModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    int row = index.row();
    int col = index.column();
    QJsonObject obj = dataList.at(row).toObject();

    switch(role){
    case Qt::DisplayRole:
    {
        switch (col) {
        case 0:
            return row + 1;
        case 1:
            return obj[headtitle.at(1)].toString();
        case 2:
            return obj[headtitle.at(2)].toString();
        case 3:
            return obj[headtitle.at(3)].toString();
        case 4:
        {
            QPushButton *button = static_cast<QPushButton*>(index.internalPointer());
            button->setText(obj[headtitle.at(4)].toString());
      //      button->setStyleSheet(QString("background-color: %1").arg(obj[headtitle.at(4)].toString()));
            return obj[headtitle.at(4)].toString();
        }
        default:
            break;
        }
    }
        break;
    case Qt::TextAlignmentRole:
        {
            if(col == 0)
                return Qt::AlignCenter;
        }
        return Qt::AlignLeft + Qt::AlignVCenter;
        break;
    case Qt::ForegroundRole:
           switch (col) {
           case 1:
               //return  info.isLive? QVariant(QColor("#7ebdfd")):QVariant(QColor("#ee6666"));
               break;
           default:
               break;
           }
        break;
    case  Qt::CheckStateRole:
    {
        QJsonObject obj = dataList.at(row).toObject();
        if (index.column() == 2)
        {
            return obj[headtitle.at(2)].toBool() == true ? Qt::Checked : Qt::Unchecked;
        }
        else if (index.column() == 3)
        {
            return obj[headtitle.at(3)].toBool() == true ? Qt::Checked : Qt::Unchecked;
        }
    }
    }

    return QVariant();
}

bool MissionModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if(!index.isValid())
        return false;
    int row = index.row();
    int col = index.column();
    QModelIndex m_index_name = this->index(row,1);
    QModelIndex m_index_color = this->index(row,4);
    QVariant missionName = this->data(m_index_name);
    QVariant missionColor = this->data(m_index_color);
//    if (role == Qt::CheckStateRole && (col == 2 || col == 3) )
//    {
//        QJsonObject obj = dataList[row].toObject();
//        obj[headtitle.at(col)] = value == Qt::Checked;
//        dataList[row] = obj;

//        if( !JsonTool::save_json_file<QJsonArray>(file_name, dataList) )
//        {
//            QMessageBox::information( nullptr, QStringLiteral("修改失败"), QStringLiteral("修改失败"));
//        }
//    }
    if (role == Qt::CheckStateRole && col == 2 )
    {
        QJsonObject obj = dataList[row].toObject();
        obj[headtitle.at(col)] = value == Qt::Checked;
        dataList[row] = obj;

        if(obj[headtitle.at(2)].toBool() == true)
        {
            emit missionFollow_send(missionName, missionColor);
            return true;
        }
        if( !JsonTool::save_json_file<QJsonArray>(file_name, dataList) )
        {
            QMessageBox::information( nullptr, QStringLiteral("修改失败"), QStringLiteral("修改失败"));
        }
    }
    else if (role == Qt::CheckStateRole && col == 3 )
    {
        QJsonObject obj = dataList[row].toObject();
        obj[headtitle.at(col)] = value == Qt::Checked;
        dataList[row] = obj;

        if(obj[headtitle.at(2)].toBool() == true)
        {
            emit namePlate_show(missionName);
            return true;
        }
        if( !JsonTool::save_json_file<QJsonArray>(file_name, dataList) )
        {
            QMessageBox::information( nullptr, QStringLiteral("修改失败"), QStringLiteral("修改失败"));
        }
    }
    return true;
}

void MissionModel::refresh()
{
    beginResetModel();
    //...
    endResetModel();
}

//这个是我自己写的
QJsonObject MissionModel::getItemData(int index)
{
    return dataList.at(index).toObject();
}


void MissionModel::init_data()
{
    file_name = QString("%1/config/fc_config/%2_%3.json").arg(QCoreApplication::applicationDirPath()).arg(plane_name).arg(mission_name);

    if(QFile::exists(file_name))
    {
        QJsonArray json_array = JsonTool::load_jsonarray_file(file_name);
        //dataList. .clear();
        for(int i = 0; i < json_array.size(); i++)
        {
            dataList.append(json_array.at(i).toObject());
        }
    }
    else
    {
        //dataList.clear();

        QString tmp_file_name = QString("%1/config/fc_config/%2.json").arg(QCoreApplication::applicationDirPath()).arg(plane_name);        
        QJsonObject obj = JsonTool::load_json_file(tmp_file_name);

        QStringList keys = obj.keys();
        if(keys.empty())
        {
            qWarning()<<"read a empty obj: "<<tmp_file_name<<endl;
            return;
        }

        QJsonArray json_array;
        foreach (QString key, keys)
        {
            QJsonObject item;
            item.insert(QStringLiteral("项目名称"), key);
            item.insert(QStringLiteral("实时关注"), false);
            item.insert(QStringLiteral("铭牌显示"), false);
            item.insert(QStringLiteral("颜色"), "#ffffff");

            json_array.append(item);
            dataList.append(item);
        }

        JsonTool::save_json_file<QJsonArray>(file_name, json_array);
    }

    color_buttons.clear();
    for(int i = 0; i<dataList.size(); i++)
    {
        QPushButton* button_p = new QPushButton();
        connect(button_p, &QPushButton::clicked, this, [=](){
            QColor color = QColorDialog::getColor();
            if (color.isValid()) {
                QPushButton *button = qobject_cast<QPushButton *>(sender());
                if (button)
                {
           //         button->setStyleSheet(QString("background-color: %1").arg(color.name()));

                    QJsonObject obj = dataList[i].toObject();
                    obj[headtitle.at(4)] = color.name();
                    dataList[i] = obj;

                    if( !JsonTool::save_json_file<QJsonArray>(file_name, dataList) )
                    {
                        QMessageBox::information( nullptr, QStringLiteral("修改失败"), QStringLiteral("修改失败"));
                    }
                }
            }
        });
        color_buttons.insert(i, button_p);
    }
}
相关推荐
----云烟----15 分钟前
QT中QString类的各种使用
开发语言·qt
「QT(C++)开发工程师」6 小时前
【qt版本概述】
开发语言·qt
一路冰雨10 小时前
Qt打开文件对话框选择文件之后弹出两次
开发语言·qt
老赵的博客11 小时前
QT 自定义界面布局要诀
开发语言·qt
码码哈哈0.011 小时前
VSCode 2022 离线安装插件QT VSTOOl报错此扩展不能安装在任何当前安装的产品上。
ide·vscode·qt
feiyangqingyun15 小时前
Qt/C++离线地图的加载和交互/可以离线使用/百度和天地图离线/支持手机上运行
c++·qt·qt天地图·qt离线地图·qt地图导航
gz94561 天前
windows下,用CMake编译qt项目,出现错误By not providing “FindQt5.cmake“...
开发语言·qt
「QT(C++)开发工程师」1 天前
Ubuntu 26.04 LTS 大升级:Qt 6 成为未来新引擎
qt
兆。1 天前
python实战案例----使用 PyQt5 构建简单的 HTTP 接口测试工具
爬虫·python·qt
喝哈喝哈1 天前
pycharm中配置pyqt5
python·qt·pycharm