Qt Creator(C++)如何向TableView动态添加自定义对象并增删数据?
解决方案:自定义模型实现
mydata属性与TableView绑定 作为Qt新手,你觉得用QStandardItemModel必须指定行列号来操作数据太繁琐是完全可以理解的——JavaFX的ObservableList确实提供了更直观的方式。不过Qt的模型/视图框架同样能实现类似的便捷操作,核心是自定义一个适配你mydata对象的表格模型,这样就能直接将对象属性映射到列,并且无需手动指定行列号来完成插入、删除操作。
步骤1:改造mydata类,适配Qt属性系统
首先,我们需要给mydata类添加Qt属性声明(Q_PROPERTY),这样自定义模型可以通过Qt的元对象系统便捷地访问对象的属性值。
mydata.h
#ifndef MYDATA_H #define MYDATA_H #include <QObject> // 必须继承QObject才能使用元对象系统 class mydata : public QObject { Q_OBJECT // 声明每个属性,格式:Q_PROPERTY(类型 属性名 READ 获取函数 WRITE 设置函数) Q_PROPERTY(QString Account READ getAccount WRITE setAccount) Q_PROPERTY(QString Exchange READ getExchange WRITE setExchange) Q_PROPERTY(QString Orderstatus READ getOrderstatus WRITE setOrderstatus) Q_PROPERTY(QString Clorid READ getClorid WRITE setClorid) public: explicit mydata(QObject *parent = nullptr); // 属性的获取函数 QString getAccount() const; QString getExchange() const; QString getOrderstatus() const; QString getClorid() const; // 属性的设置函数(可选,如果你需要修改属性的话) void setAccount(const QString &value); void setExchange(const QString &value); void setOrderstatus(const QString &value); void setClorid(const QString &value); private: QString Account; QString Exchange; QString Orderstatus; QString Clorid; }; #endif // MYDATA_H
mydata.cpp
#include "mydata.h" mydata::mydata(QObject *parent) : QObject(parent) { Account = "finsoldts5"; Exchange = "CME"; Orderstatus = "Filled"; Clorid = "CME"; } QString mydata::getAccount() const { return Account; } QString mydata::getExchange() const { return Exchange; } QString mydata::getOrderstatus() const { return Orderstatus; } QString mydata::getClorid() const { return Clorid; } void mydata::setAccount(const QString &value) { Account = value; } void mydata::setExchange(const QString &value) { Exchange = value; } void mydata::setOrderstatus(const QString &value) { Orderstatus = value; } void mydata::setClorid(const QString &value) { Clorid = value; }
步骤2:自定义表格模型MyTableModel
接下来我们创建一个继承自QAbstractTableModel的模型类,内部维护一个mydata对象的列表,重写必要的虚函数来实现数据映射,同时添加便捷的插入、删除方法。
mytablemodel.h
#ifndef MYTABLEMODEL_H #define MYTABLEMODEL_H #include <QAbstractTableModel> #include <QList> #include "mydata.h" class MyTableModel : public QAbstractTableModel { Q_OBJECT public: explicit MyTableModel(QObject *parent = nullptr); // 重写模型的核心方法 int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; // 自定义的便捷操作方法 void addData(mydata *data); // 添加一条数据到表格末尾 void removeLastData(); // 删除最后一行数据 void removeData(int row); // 删除指定行数据 private: QList<mydata*> m_dataList; // 存储所有mydata对象的列表 }; #endif // MYTABLEMODEL_H
mytablemodel.cpp
#include "mytablemodel.h" MyTableModel::MyTableModel(QObject *parent) : QAbstractTableModel(parent) { } int MyTableModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_dataList.size(); // 行数等于数据列表的大小 } int MyTableModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return 4; // 对应mydata的4个属性 } QVariant MyTableModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || role != Qt::DisplayRole) { return QVariant(); } mydata *data = m_dataList.at(index.row()); switch (index.column()) { case 0: return data->getAccount(); case 1: return data->getExchange(); case 2: return data->getOrderstatus(); case 3: return data->getClorid(); default: return QVariant(); } } QVariant MyTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole || orientation != Qt::Horizontal) { return QVariant(); } // 设置列标题 switch (section) { case 0: return "Account"; case 1: return "Exchange"; case 2: return "Order Status"; case 3: return "Clorid"; default: return QVariant(); } } void MyTableModel::addData(mydata *data) { // 通知模型即将插入一行(末尾) beginInsertRows(QModelIndex(), m_dataList.size(), m_dataList.size()); m_dataList.append(data); // 通知模型插入完成,视图会自动刷新 endInsertRows(); } void MyTableModel::removeLastData() { if (m_dataList.isEmpty()) { return; } // 通知模型即将删除最后一行 beginRemoveRows(QModelIndex(), m_dataList.size()-1, m_dataList.size()-1); delete m_dataList.takeLast(); // 释放内存 endRemoveRows(); } void MyTableModel::removeData(int row) { if (row < 0 || row >= m_dataList.size()) { return; } beginRemoveRows(QModelIndex(), row, row); delete m_dataList.takeAt(row); endRemoveRows(); }
步骤3:在主函数中使用自定义模型
现在我们可以在主函数中创建模型、TableView,并且演示如何添加/删除数据——完全不需要指定行列号,只需要操作MyTableModel的方法即可。
main.cpp
#include <QApplication> #include <QTableView> #include <QPushButton> #include <QVBoxLayout> #include <QWidget> #include "mytablemodel.h" #include "mydata.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); // 创建主窗口和布局 QWidget *window = new QWidget(); QVBoxLayout *layout = new QVBoxLayout(window); // 创建自定义模型 MyTableModel *model = new MyTableModel(); // 初始化一些测试数据 model->addData(new mydata()); model->addData(new mydata()); // 创建一个不同的测试数据 mydata *customData = new mydata(); customData->setAccount("testAccount123"); customData->setOrderstatus("Pending"); model->addData(customData); // 创建TableView并设置模型 QTableView *tableView = new QTableView(); tableView->setModel(model); tableView->horizontalHeader()->setStretchLastSection(true); // 最后一列自适应宽度 tableView->resizeColumnsToContents(); // 列宽适配内容 // 创建按钮演示添加/删除操作 QPushButton *addBtn = new QPushButton("添加新数据"); QPushButton *removeBtn = new QPushButton("删除最后一行"); // 绑定按钮点击事件 QObject::connect(addBtn, &QPushButton::clicked, [=](){ // 每次点击创建一个新的mydata对象(可以自定义属性值) mydata *newData = new mydata(); static int count = 1; newData->setAccount(QString("newAccount%1").arg(count)); newData->setOrderstatus(count % 2 == 0 ? "Filled" : "Pending"); count++; model->addData(newData); tableView->resizeColumnsToContents(); // 重新适配列宽 }); QObject::connect(removeBtn, &QPushButton::clicked, [=](){ model->removeLastData(); }); // 添加控件到布局 layout->addWidget(tableView); layout->addWidget(addBtn); layout->addWidget(removeBtn); window->resize(600, 400); window->show(); return a.exec(); }
关键说明
- Qt属性系统:通过
Q_PROPERTY声明属性,让模型可以安全地访问mydata的字段,这是Qt模型/视图框架的核心机制之一。 - 自定义模型的通知机制:
beginInsertRows和endInsertRows(以及对应的删除方法)是必须的——它们会通知视图数据发生了变化,视图才会自动刷新,这和JavaFX中ObservableList的自动通知类似。 - 内存管理:示例中
mydata对象是用new创建的,在删除数据时我们调用了delete来释放内存,如果你不想手动管理内存,可以改用QList<mydata>值类型(需要mydata支持拷贝构造)。
这个实现完全满足你的需求:
mydata的四个属性自动映射到表格的4列- 添加数据只需要调用
addData,自动添加到表格末尾,无需指定行列号 - 删除数据可以通过
removeLastData或removeData完成,同样无需手动操作行列
内容的提问来源于stack exchange,提问作者hema chandra




