Qt自定义模型示例

cpp 复制代码
#pragma once

#include <QAbstractTableModel>
#include <QVariant>

class MyTableModel :public QAbstractTableModel {
	Q_OBJECT
public:
	MyTableModel(QObject* parent = nullptr):QAbstractTableModel(parent){}
	int rowCount(const QModelIndex &parent = QModelIndex()) const override {
		return 5;
	}
	int columnCount(const QModelIndex &parent = QModelIndex()) const override {
		return 3;
	}
	QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
		if (!index.isValid() || role != Qt::DisplayRole) {
			return QVariant();
		}
		return index.row() + index.column();
	}
};
cpp 复制代码
#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication1.h"
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include "MyTableModel.hpp"

class QtWidgetsApplication1 : public QMainWindow
{
    Q_OBJECT

public:
    QtWidgetsApplication1(QWidget *parent = nullptr);
    ~QtWidgetsApplication1();

	MyTableModel myModel;

private:
    Ui::QtWidgetsApplication1Class ui;
};
cpp 复制代码
#include "QtWidgetsApplication1.h"

QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
	//为UI设置模型
	ui.tableView->setModel(&myModel);
}

QtWidgetsApplication1::~QtWidgetsApplication1()
{}

表格样式:

Qt模型中的role是用来在数据项(通常是表格模型中的单元格)上标识不同的数据信息的。每个数据项可以有多个role,每个role代表不同的数据信息,例如显示的文本、图标、背景色等。

在Qt中,通过Qt::ItemDataRole枚举定义了不同的预定义角色:

复制代码
复制代码

enum ItemDataRole {

DisplayRole = 0, // 显示的文本

DecorationRole, // 用于装饰数据的,例如图标

EditRole, // 可编辑的数据

ToolTipRole, // 工具提示

StatusTipRole, // 状态提示

WhatsThisRole, // "What's This?" 帮助信息

SizeHintRole, // 数据项的大小提示

FontRole, // 字体信息

TextAlignmentRole, // 文本对齐方式

BackgroundColorRole, // 背景色

// ... 等等

};

自定义角色时,可以使用Qt::UserRole + 1开始扩展。

例如,下面的代码演示了如何在自定义的表格模型中实现不同的role:

复制代码
复制代码

QVariant MyTableModel::data(const QModelIndex &index, int role) const {

if (!index.isValid())

return QVariant();

if (role == Qt::TextColorRole) {

// 返回文字颜色

return QColor(Qt::red);

} else if (role == Qt::DisplayRole) {

// 返回显示的文本

return "显示文本";

} else if (role == Qt::DecorationRole) {

// 返回装饰用的图标

return QIcon("path_to_icon");

}

// ... 其他角色的处理

return QVariant();

}

Qt::ItemFlags MyTableModel::flags(const QModelIndex &index) const {

Qt::ItemFlags flags = QAbstractItemModel::flags(index);

if (index.isValid()) {

// 设置可编辑

flags |= Qt::ItemIsEditable;

// 设置可以设置背景色

flags |= Qt::ItemNeverHasAttributes;

}

return flags;

}

在这个例子中,我们定义了两个role:Qt::TextColorRoleQt::DisplayRole,并且在flags函数中设置了这些role是可以被应用的。在实际的数据获取函数data中,我们根据传入的role值来返回不同的数据。

cpp 复制代码
QVariant MyTableModel::data(const QModelIndex &index, int role) const override {
		if (!index.isValid())
			return QVariant();

		if (role == Qt::DisplayRole) {
			// 返回用于显示的数据
			return QString("行 %1, 列 %2").arg(index.row() + 1).arg(index.column() + 1);
		}
		else if (role == Qt::FontRole) {
			QFont font;
			font.setBold(true);
			return font;
		}
		else if (role == Qt::BackgroundRole) {
			return QBrush(Qt::lightGray);
		}
		return QVariant();
	}
交互和编辑功能:
cpp 复制代码
//通过实现模型的 setData() 方法来响应数据的更改。
	bool MyTableModel::setData(const QModelIndex &index, const QVariant &value, int role) {
		if (index.isValid() && role == Qt::EditRole)
			return true;
		return false;
	}
	//为了启用编辑功能,还需要在模型中实现 flags() 方法,并返回合适的标志。
	Qt::ItemFlags MyTableModel::flags(const QModelIndex &index) const {
		if (!index.isValid())
			return Qt::ItemIsEnabled;
		return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
	}

完整示例:

cpp 复制代码
#pragma once

#include <QAbstractTableModel>
#include <QVariant>
#include <QFont>
#include <QBrush>
#include <QList>
#include <QPair>

class MyTableModel :public QAbstractTableModel {
	Q_OBJECT
public:
	MyTableModel(QObject* parent = nullptr):QAbstractTableModel(parent){
		employees << QPair<QString, QString>("Alice", "HR")
			<< QPair<QString, QString>("Bob", "IT")
			<< QPair<QString, QString>("Carol", "Finance");
	}
	int rowCount(const QModelIndex &parent = QModelIndex()) const override {
		return employees.count();
	}
	int columnCount(const QModelIndex &parent = QModelIndex()) const override {
		return 2;
	}
	QVariant MyTableModel::data(const QModelIndex &index, int role) const override {
		if (!index.isValid() || role != Qt::DisplayRole)
			return QVariant();
		const auto &employee = employees[index.row()];
		if (index.column() == 0) return employee.first;
		if (index.column() == 1) return employee.second;
		return QVariant();
	}
	//通过实现模型的 setData() 方法来响应数据的更改。
	bool MyTableModel::setData(const QModelIndex &index, const QVariant &value, int role) {
		if (index.isValid() && role == Qt::EditRole)
			return true;
		return false;
	}
	//为了启用编辑功能,还需要在模型中实现 flags() 方法,并返回合适的标志。
	Qt::ItemFlags MyTableModel::flags(const QModelIndex &index) const {
		if (!index.isValid())
			return Qt::ItemIsEnabled;
		return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
	}
private:
	QList<QPair<QString, QString>> employees;
};
cpp 复制代码
#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication1.h"
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include "MyTableModel.hpp"
#include <QSortFilterProxyModel>

class QtWidgetsApplication1 : public QMainWindow
{
    Q_OBJECT

public:
    QtWidgetsApplication1(QWidget *parent = nullptr);
    ~QtWidgetsApplication1();

	MyTableModel myModel;
	QSortFilterProxyModel proxyModel;

private:
    Ui::QtWidgetsApplication1Class ui;
};
cpp 复制代码
#include "QtWidgetsApplication1.h"

QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
	//设置源模型
	proxyModel.setSourceModel(&myModel);
	//为UI设置模型
	ui.tableView->setModel(&proxyModel);
	//启用排序
	ui.tableView->setSortingEnabled(true);
}

QtWidgetsApplication1::~QtWidgetsApplication1()
{}
相关推荐
HyperAI超神经1 分钟前
在线教程|DeepSeek-OCR 2公式/表格解析同步改善,以低视觉token成本实现近4%的性能跃迁
开发语言·人工智能·深度学习·神经网络·机器学习·ocr·创业创新
晚霞的不甘8 分钟前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频
SunnyDays101110 分钟前
使用 Java 冻结 Excel 行和列:完整指南
java·冻结excel行和列
R_.L11 分钟前
【QT】常用控件(按钮类控件、显示类控件、输入类控件、多元素控件、容器类控件、布局管理器)
开发语言·qt
Zach_yuan20 分钟前
自定义协议:实现网络计算器
linux·服务器·开发语言·网络
摇滚侠21 分钟前
在 SpringBoot 项目中,开发工具使用 IDEA,.idea 目录下的文件需要提交吗
java·spring boot·intellij-idea
云姜.26 分钟前
java多态
java·开发语言·c++
李堇29 分钟前
android滚动列表VerticalRollingTextView
android·java
CoderCodingNo35 分钟前
【GESP】C++五级练习题 luogu-P1865 A % B Problem
开发语言·c++·算法
陳103041 分钟前
C++:红黑树
开发语言·c++