当前位置: 首页 > news >正文

qt AbstractTableModel

表格模型(非树形),提供一个更简单的 QAbstractTableModel 示例
 
 
Qwen3-Max

当然可以!下面是一个基于 QAbstractTableModel 的简单表格模型示例,展示如何显示一个二维数据表(比如人员信息:姓名、年龄、城市)。

QAbstractTableModelQAbstractItemModel 的子类,专为表格(行 × 列)结构设计,使用起来比通用的 QAbstractItemModel 更简单,因为你不需要处理树形父子关系。


📋 示例:人员信息表格模型

1. 自定义模型头文件(PersonTableModel.h)

cpp
编辑
// PersonTableModel.h
#ifndef PERSONTABLEMODEL_H
#define PERSONTABLEMODEL_H#include <QAbstractTableModel>
#include <QStringList>
#include <QVector>struct Person {QString name;int age;QString city;Person(const QString &n, int a, const QString &c): name(n), age(a), city(c) {}
};class PersonTableModel : public QAbstractTableModel
{Q_OBJECTpublic:explicit PersonTableModel(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;// 可选:支持编辑bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;Qt::ItemFlags flags(const QModelIndex &index) const override;// 辅助函数:添加数据void addPerson(const Person &person);void clear();private:QList<Person> m_people;QStringList m_headers = {"姓名", "年龄", "城市"};
};#endif // PERSONTABLEMODEL_H

2. 模型实现(PersonTableModel.cpp)

cpp
编辑
// PersonTableModel.cpp
#include "PersonTableModel.h"
#include <QVariant>PersonTableModel::PersonTableModel(QObject *parent): QAbstractTableModel(parent)
{
}int PersonTableModel::rowCount(const QModelIndex &) const
{return m_people.size();
}int PersonTableModel::columnCount(const QModelIndex &) const
{return 3; // name, age, city
}QVariant PersonTableModel::data(const QModelIndex &index, int role) const
{if (!index.isValid() || role != Qt::DisplayRole)return QVariant();const Person &p = m_people[index.row()];switch (index.column()) {case 0: return p.name;case 1: return p.age;case 2: return p.city;default: return QVariant();}
}QVariant PersonTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {if (section >= 0 && section < m_headers.size())return m_headers[section];}return QAbstractTableModel::headerData(section, orientation, role);
}bool PersonTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{if (!index.isValid() || role != Qt::EditRole)return false;Person &p = m_people[index.row()];switch (index.column()) {case 0: p.name = value.toString(); break;case 1: p.age = value.toInt(); break;case 2: p.city = value.toString(); break;default: return false;}emit dataChanged(index, index);return true;
}Qt::ItemFlags PersonTableModel::flags(const QModelIndex &index) const
{if (!index.isValid())return Qt::NoItemFlags;return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}void PersonTableModel::addPerson(const Person &person)
{beginInsertRows(QModelIndex(), m_people.size(), m_people.size());m_people.append(person);endInsertRows();
}void PersonTableModel::clear()
{beginResetModel();m_people.clear();endResetModel();
}

3. 主函数:在 QTableView 中显示

cpp
编辑
// main.cpp
#include <QApplication>
#include <QTableView>
#include "PersonTableModel.h"int main(int argc, char *argv[])
{QApplication app(argc, argv);PersonTableModel model;model.addPerson(Person("张三", 28, "北京"));model.addPerson(Person("李四", 34, "上海"));model.addPerson(Person("王五", 22, "广州"));QTableView view;view.setModel(&model);view.resize(400, 200);view.setWindowTitle("QAbstractTableModel 示例");view.show();return app.exec();
}

✅ 编译配置(.pro 文件)

pro
编辑
QT += widgets
CONFIG += c++17
SOURCES += main.cpp PersonTableModel.cpp
HEADERS += PersonTableModel.h

🔍 关键点说明

  • rowCount() / columnCount():返回行数和列数。
  • data():提供显示内容(通常处理 Qt::DisplayRole)。
  • headerData():设置表头。
  • setData() + flags():使单元格可编辑(可选)。
  • beginInsertRows() / endInsertRows():安全地插入新行并通知视图更新。

这个例子比树模型更轻量,适合大多数表格场景。如果你只需要只读表格,可以省略 setData()flags()

需要我加上排序、自定义委托(delegate)、或从 CSV 加载数据等功能吗?

|
 
 
同时支持拖拽
 
 
Qwen3-Max
19:50:16

好的!下面是在前面的 QAbstractTableModel 表格模型基础上,增加拖拽(Drag & Drop)支持的完整示例。

我们将实现:

  • ✅ 拖出(Drag):可以从表格中拖出一行数据(例如拖到桌面或其他应用)。
  • ✅ 拖入(Drop):可以将外部文本(如纯文本或自定义格式)拖入表格,新增一行。
  • 使用 MIME 类型 自定义数据格式(如 "application/x-person")。

🔧 修改点概览

  1. 在 PersonTableModel 中重写:
    • mimeTypes()
    • mimeData()
    • dropMimeData()
    • supportedDropActions()
  2. 设置 QTableView 启用拖拽:
    • setDragEnabled(true)
    • setAcceptDrops(true)
    • setDropIndicatorShown(true)
    • setSelectionMode(QAbstractItemView::SingleSelection)(可选)
  3. 模型需支持插入行(已有 addPerson)。

✅ 完整代码(仅展示修改/新增部分)

1. PersonTableModel.h —— 新增拖拽相关声明

在类中添加:

cpp
编辑
// PersonTableModel.h (追加到 public: 下)
QStringList mimeTypes() const override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
bool dropMimeData(const QMimeData *data, Qt::DropAction action,int row, int column, const QModelIndex &parent) override;
Qt::DropActions supportedDropActions() const override;

注意:包含 <QMimeData><QDataStream> 头文件。

完整头文件顶部应包含:

cpp
编辑
#include <QAbstractTableModel>
#include <QList>
#include <QStringList>
#include <QMimeData>

2. PersonTableModel.cpp —— 实现拖拽逻辑

.cpp 文件末尾添加以下实现:

cpp
编辑
// MIME 类型:自定义格式
QStringList PersonTableModel::mimeTypes() const
{return {"application/x-person", "text/plain"};
}// 将选中的行打包为 MIME 数据
QMimeData *PersonTableModel::mimeData(const QModelIndexList &indexes) const
{if (indexes.isEmpty())return nullptr;// 获取唯一行(因为是整行选择)QSet<int> rows;for (const auto &index : indexes)rows.insert(index.row());QByteArray encodedData;QDataStream stream(&encodedData, QIODevice::WriteOnly);for (int row : rows) {const Person &p = m_people[row];stream << p.name << p.age << p.city;}QMimeData *mimeData = new QMimeData;mimeData->setData("application/x-person", encodedData);// 同时提供纯文本备用(方便拖到记事本等)QStringList textLines;for (int row : rows) {const Person &p = m_people[row];textLines << QString("%1, %2, %3").arg(p.name).arg(p.age).arg(p.city);}mimeData->setText(textLines.join('\n'));return mimeData;
}// 支持的拖放动作
Qt::DropActions PersonTableModel::supportedDropActions() const
{return Qt::CopyAction | Qt::MoveAction;
}// 处理拖入的数据
bool PersonTableModel::dropMimeData(const QMimeData *data,Qt::DropAction action,int row, int column,const QModelIndex &parent)
{Q_UNUSED(column);Q_UNUSED(parent);if (action == Qt::IgnoreAction)return true;// 优先使用自定义格式if (data->hasFormat("application/x-person")) {QByteArray encoded = data->data("application/x-person");QDataStream stream(&encoded, QIODevice::ReadOnly);int beginRow = (row != -1) ? row : rowCount(); // 拖到空白处则追加while (!stream.atEnd()) {QString name;int age;QString city;stream >> name >> age >> city;beginInsertRows(QModelIndex(), beginRow, beginRow);m_people.insert(beginRow, Person(name, age, city));++beginRow;}endInsertRows();return true;}// 支持从外部拖入纯文本(每行格式:name, age, city)if (data->hasText()) {QStringList lines = data->text().split('\n');int beginRow = (row != -1) ? row : rowCount();for (const QString &line : lines) {if (line.trimmed().isEmpty()) continue;QStringList parts = line.split(',');if (parts.size() >= 3) {QString name = parts[0].trimmed();bool ok;int age = parts[1].trimmed().toInt(&ok);QString city = parts[2].trimmed();if (ok) {beginInsertRows(QModelIndex(), beginRow, beginRow);m_people.insert(beginRow, Person(name, age, city));++beginRow;}}}endInsertRows();return true;}return false;
}

3. main.cpp —— 启用视图的拖拽

修改主函数:

cpp
编辑
// main.cpp
#include <QApplication>
#include <QTableView>
#include "PersonTableModel.h"int main(int argc, char *argv[])
{QApplication app(argc, argv);PersonTableModel model;model.addPerson(Person("张三", 28, "北京"));model.addPerson(Person("李四", 34, "上海"));QTableView view;view.setModel(&model);// 启用拖拽view.setDragEnabled(true);           // 允许拖出view.setAcceptDrops(true);           // 允许拖入view.setDropIndicatorShown(true);    // 显示插入线view.setDragDropMode(QAbstractItemView::DragDrop); // 支持拖入和拖出view.setDefaultDropAction(Qt::CopyAction);view.resize(450, 200);view.setWindowTitle("支持拖拽的 QAbstractTableModel");view.show();return app.exec();
}

🧪 测试拖拽功能

  • 拖出:选中一行,拖到桌面(会生成文本),或拖到另一个支持此 MIME 类型的应用。
  • 拖入
    • 从其他支持 "application/x-person" 的实例拖入(如另一个该程序窗口)。
    • 或从记事本复制一行 "赵六, 25, 深圳",直接拖进表格 → 自动解析并新增。

⚠️ 注意事项

  • 拖拽多行时,我们用 QSet<int> 去重,避免同一行多次拖出。
  • row == -1 表示拖到视图空白区域(通常应追加到末尾)。
  • 若需 移动而非复制(如内部拖拽),可在 dropMimeData 中删除原行(本例默认只做复制)。
http://www.jsqmd.com/news/183176/

相关文章:

  • 迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法是图论中最经典的两种最短路径算法
  • AI试验数据综合分析管理系统:数据价值的技术解码器
  • AWS WAF Rate Limit 与 Shield DDoS 防护最佳实践
  • Springboot基于Web的绿色环保网站0z5t9(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 032.有序表之AVL树
  • 微PE官网启动盘制作+Sonic环境部署一体化方案
  • 信号与系统综述
  • Sonic数字人前端表格展示可用VXETable官方组件实现
  • HuggingFace镜像网站对比:哪家更适合拉取VoxCPM-1.5-TTS-WEB-UI?
  • 1.2.1 - f
  • 删除具有大量部署的cloudflare pages项目
  • 文本转语音新突破:VoxCPM-1.5实现高效标记率6.25Hz
  • 20260102 之所思 - 人生如梦
  • UltraISO制作U盘启动盘同时部署VoxCPM-1.5-TTS-WEB-UI运行环境
  • 输电杆塔绝缘子红外测温图像检测数据集VOC+YOLO格式420张1类别
  • Blender动画协作?为3D角色赋予真实声音
  • Sonic支持1080P输出?关键在于min_resolution设为1024
  • 导师推荐!8款AI论文软件测评:本科生写论文还能这么快
  • 水务集团停水通知自动化语音外呼系统
  • 对比主流TTS模型:VoxCPM-1.5的优势与性能表现
  • 知识库建设:沉淀常见Sonic使用问题的答案
  • VoxCPM-1.5-TTS-WEB-UI与Git Commit版本控制协同工作流程
  • 公交移动电视:车载屏幕配合VoxCPM-1.5-TTS-WEB-UI播报站点周边信息
  • Python基于改进粒子群IPSO与LSTM的短期电力负荷预测研究
  • 深入解析:18、论文阅读:AOD-Net:一体化除雾网络
  • 实用指南:AI智能分析高空抛物算法方案
  • The Sandbox玩家用Sonic创建个性化Avatar发言
  • 计算机毕设java心理问题档案管理系统 基于Java的心理健康档案信息化管理系统设计与实现 Java技术驱动的心理咨询档案数字化管理平台构建
  • Sonic数字人监控指标设计:GPU利用率、请求成功率等
  • 提升数字人自然度的关键参数调节指南(Sonic专属)