首先在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]);}elsereturn 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,那么选中状态boolQt::TextAlignmentRole: Qt::DisplayRole: Qt::CheckStateRole:enum ItemDataRole {DisplayRole = 0,DecorationRole = 1,EditRole = 2,ToolTipRole = 3,StatusTipRole = 4,WhatsThisRole = 5,// MetadataFontRole = 6,TextAlignmentRole = 7,BackgroundRole = 8,ForegroundRole = 9,
#if QT_DEPRECATED_SINCE(5, 13) // ### Qt 6: remove meBackgroundColorRole Q_DECL_ENUMERATOR_DEPRECATED = BackgroundRole,TextColorRole Q_DECL_ENUMERATOR_DEPRECATED = ForegroundRole,
#endifCheckStateRole = 10,// AccessibilityAccessibleTextRole = 11,AccessibleDescriptionRole = 12,// More general purposeSizeHintRole = 13,InitialSortOrderRole = 14,// Internal UiLib roles. Start worrying when public roles go that high.DisplayPropertyRole = 27,DecorationPropertyRole = 28,ToolTipPropertyRole = 29,StatusTipPropertyRole = 30,WhatsThisPropertyRole = 31,// ReservedUserRole = 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);}
}