目錄
- @[TOC](目錄)
- 前言
- 一、初步介紹
- 二、QSqlQueryModel
- 1.基礎定位
- 2.特點
- 3.核心接口
- 4.典型用法
- 5.優缺點
- 三、QSqlTableModel
- 1.基礎定位
- 2.特點
- 3.核心接口
- 4.典型用法
- 5.優缺點
- 四、QSqlRelationalTableModel
- 1.基礎定位
- 2.特點
- 3.核心接口
- 4.典型用法 (示例:employees表有 dept_id外鍵,關聯 departments表的 id和 name字段)
- 5.優缺點
- 五、重要注意事項
目錄
- @[TOC](目錄)
- 前言
- 一、初步介紹
- 二、QSqlQueryModel
- 1.基礎定位
- 2.特點
- 3.核心接口
- 4.典型用法
- 5.優缺點
- 三、QSqlTableModel
- 1.基礎定位
- 2.特點
- 3.核心接口
- 4.典型用法
- 5.優缺點
- 四、QSqlRelationalTableModel
- 1.基礎定位
- 2.特點
- 3.核心接口
- 4.典型用法 (示例:employees表有 dept_id外鍵,關聯 departments表的 id和 name字段)
- 5.優缺點
- 五、重要注意事項
前言
本文主要介紹的是使用代碼生成的情況下對控件的介紹,包括擁有的功能及能修改的樣式,也會說明在qtdesiner拖拽控件生成和使用代碼生成控件的區別(如果有的話,遇到了的會說),此版本不屬于最終版本,以后遇到什么新奇的點會繼續更新!本文基于QT官方的文檔進行的編寫,QT版本為qt 5.14.0,編寫環境為Windows11。不得不說官方文檔真是個好東西,有時候有些不會的上去一看就能有靈感解決了,可惜沒有中文版本的。
一、初步介紹
因為這三個模型類基本都是將SQL數據庫中的數據引入模型的,用到的機會也不是很多,所以就放在一起介紹了。
?核心目標:?? 將數據庫查詢結果或表數據無縫展示在 Qt 的視圖控件(如 QTableView、QListView)中,并支持一定程度的數據操作(編輯、插入、刪除)。
??共同基礎:??
??依賴 Qt SQL 模塊:?? 使用前需包含 ,并在項目文件 (.pro) 中添加 QT += sql。
??需要數據庫連接:?? 使用前必須建立有效的數據庫連接 (QSqlDatabase)。
??視圖綁定:?? 通過 view->setModel(model)將模型綁定到視圖。
??數據角色:?? 通過 data(index, role)獲取數據,支持 Qt::DisplayRole(顯示文本)、Qt::EditRole(編輯值) 等。
??只讀屬性:?? QSqlQueryModel默認是只讀的。QSqlTableModel和 QSqlRelationalTableModel默認是可編輯的(需設置 setEditStrategy)。
??列與字段映射:?? 模型中的列 (column) 對應 SQL 查詢結果或數據庫表中的字段 (field)。
二、QSqlQueryModel
1.基礎定位
?? 用于執行任意 SQL SELECT查詢并將結果集展示在視圖中。??核心是執行查詢并獲取結果。??
2.特點
只讀 (默認):?? 僅用于顯示查詢結果,不支持通過模型直接修改數據、插入或刪除行。
??靈活性高:?? 可以執行任何 SELECT語句,包括多表連接、聚合函數、子查詢等復雜查詢。
??輕量:?? 主要職責是執行查詢和緩存結果。
??手動刷新:?? 調用 setQuery()執行新查詢來刷新數據。不自動監聽數據庫變化。
3.核心接口
// 設置/執行查詢 (刷新模型)
void setQuery(const QSqlQuery &query);
void setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase());// 獲取底層查詢對象
QSqlQuery query() const;// 獲取記錄 (行) 信息
QSqlRecord record() const; // 返回一個空記錄,包含字段信息
QSqlRecord record(int row) const; // 獲取指定行的記錄 (包含所有字段值)// 獲取字段名 (列名)
QString headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
// 通常需要重寫 headerData() 來設置列標題為字段名
4.典型用法
QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery("SELECT id, name, salary FROM employees WHERE department = 'Sales'", myDatabase);
tableView->setModel(model);
// 重寫 headerData 以顯示字段名
5.優缺點
優點: 靈活,能處理復雜查詢。
缺點: 只讀,需要手動刷新,不直接支持編輯。
三、QSqlTableModel
1.基礎定位
專門用于操作??單個數據庫表??。提供對表中數據的??讀寫??訪問(CRUD:Create, Read, Update, Delete)。
2.特點
可讀寫 (默認):?? 支持通過模型接口 (setData, insertRow, removeRow) 修改數據、插入新行、刪除行。
??基于單表:?? 操作對象是數據庫中的一個表。
??編輯策略 (EditStrategy):?? 控制修改如何提交到數據庫,是核心特性!
QSqlTableModel::OnFieldChange
:字段值改變時立即提交。(??不推薦??,效率低且易出錯)。
QSqlTableModel::OnRowChange
:當用戶選擇另一行或調用 submit()時提交當前行的所有修改。(常用)。
QSqlTableModel::OnManualSubmit
:所有修改都緩存在模型中,直到顯式調用 submitAll()或 revertAll()。(最常用,提供事務控制)。
??過濾與排序:?? 支持通過 setFilter()設置 WHERE 條件,setSort()設置 ORDER BY 條件。調用 select()應用過濾/排序并刷新數據。
??自動生成 SQL:?? 模型內部根據操作自動生成相應的 INSERT, UPDATE, DELETE語句。
3.核心接口
// 設置操作的表和數據庫
void setTable(const QString &tableName);
void setDatabase(const QSqlDatabase &db); // 通常在構造函數設置// 設置編輯策略
void setEditStrategy(QSqlTableModel::EditStrategy strategy);// 執行 SELECT 查詢 (應用過濾/排序,刷新數據)
bool select();// 設置過濾條件 (WHERE 子句,不帶 WHERE 關鍵字)
void setFilter(const QString &filter);
// 設置排序 (ORDER BY 子句,不帶 ORDER BY 關鍵字)
void setSort(int column, Qt::SortOrder order);// 數據操作
bool insertRow(int row, const QModelIndex &parent = QModelIndex()); // 插入空行
bool removeRow(int row, const QModelIndex &parent = QModelIndex()); // 刪除行
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; // 修改單元格// 提交/回滾修改 (根據 EditStrategy)
bool submit(); // 提交當前行修改 (OnRowChange)
bool submitAll(); // 提交所有緩存的修改 (OnManualSubmit)
void revert(); // 回滾當前行修改
void revertAll(); // 回滾所有緩存的修改// 獲取表結構信息
QSqlRecord record() const; // 返回一個空記錄,包含字段信息
QSqlRecord record(int row) const; // 獲取指定行的記錄
QString fieldName(int column) const; // 獲取列名 (字段名)
4.典型用法
QSqlTableModel *model = new QSqlTableModel(parent, myDatabase);
model->setTable("employees");
model->setEditStrategy(QSqlTableModel::OnManualSubmit); // 推薦
model->setFilter("department = 'Sales'"); // 設置過濾
model->setSort(2, Qt::AscendingOrder); // 按第3列(索引2)升序
model->select(); // 執行查詢,加載數據tableView->setModel(model);
tableView->setEditTriggers(QAbstractItemView::DoubleClicked); // 啟用視圖編輯// 點擊保存按鈕時提交所有修改
connect(saveButton, &QPushButton::clicked, model, &QSqlTableModel::submitAll);
// 點擊取消按鈕時回滾所有修改
connect(cancelButton, &QPushButton::clicked, model, &QSqlTableModel::revertAll);
5.優缺點
優點: 支持對單表進行完整的 CRUD 操作,集成度高,使用相對方便。
缺點: 僅限于單表操作。復雜查詢(如多表 JOIN)需要繞行或使用其他模型。OnManualSubmit需要手動管理提交。
四、QSqlRelationalTableModel
1.基礎定位
繼承自 QSqlTableModel。專門用于處理具有??外鍵 (Foreign Key)?? 關系的單表。它允許你在顯示主表記錄時,用另一個關聯表(Lookup Table)中的??友好名稱??代替原始的外鍵 ID 值。
2.特點
繼承 QSqlTableModel:?? 擁有 QSqlTableModel的所有功能(CRUD、過濾、排序、編輯策略)。
??關系映射 (Relation):?? 核心功能! 將主表中的外鍵字段映射到關聯表的某個字段(通常是顯示名稱)。
??下拉框支持:?? 在可編輯的視圖(如 QTableView)中,編輯具有關系的字段時,會自動提供一個下拉框 (QComboBox),列出關聯表中的可選值。
??內部使用 JOIN:?? 為了實現關系顯示,模型內部在執行 SELECT時會使用 LEFT JOIN(或類似)將關聯表連接進來。
3.核心接口
// 設置關系 (核心!)
void setRelation(int column, const QSqlRelation &relation);
// QSqlRelation 構造函數: QSqlRelation(tableName, fieldId, fieldDisplay)
// tableName: 關聯表名
// fieldId: 關聯表中與主表外鍵字段匹配的 ID 字段 (通常是主鍵)
// fieldDisplay: 關聯表中要顯示的友好名稱字段// 獲取關系
QSqlRelation relation(int column) const;// 獲取關聯表的模型 (可用于自定義委托等)
QSqlTableModel *relationModel(int column) const;
4.典型用法 (示例:employees表有 dept_id外鍵,關聯 departments表的 id和 name字段)
QSqlRelationalTableModel *model = new QSqlRelationalTableModel(parent, myDatabase);
model->setTable("employees");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);// 設置關系:將 employees 表的第3列 (假設是 dept_id) 映射到 departments 表的 name 字段
model->setRelation(3, QSqlRelation("departments", "id", "name"));model->select();tableView->setModel(model);// 為了讓關系列顯示友好名稱并使用下拉框,通常需要設置一個特殊的委托
tableView->setItemDelegate(new QSqlRelationalDelegate(tableView));/*
?效果:??
在 tableView中,原本顯示 dept_id(如 1, 2) 的列,現在會顯示對應的部門名稱 (如 "Sales", "Engineering")。
當用戶雙擊該列進行編輯時,會出現一個下拉框 (QComboBox),列出 departments表中所有的 name值供用戶選擇。用戶選擇后,模型內部實際存儲和操作的仍然是 dept_id。
*/
5.優缺點
優點: 極大地提升了用戶界面友好度,尤其是在處理外鍵關系時。簡化了基于外鍵的選擇操作。
缺點: 仍然基于單表(主表),復雜關系或多表 JOIN 顯示非友好名稱字段可能力不從心。性能可能略低于 QSqlTableModel(因為 JOIN 操作)。
五、重要注意事項
1、事務管理:?? QSqlTableModel和 QSqlRelationalTableModel的 submitAll()操作通常發生在數據庫事務之外。如果需要嚴格的原子性操作,應在調用 submitAll()前后手動管理 QSqlDatabase的事務 (transaction(), commit(), rollback())。
??2、性能:?? 對于大型數據集,QSqlTableModel和 QSqlRelationalTableModel默認會一次性加載所有數據到內存。考慮使用 setQuery分頁 (對 QSqlQueryModel) 或限制過濾條件來優化。
3、??復雜場景:?? 對于非常復雜的數據庫交互(如涉及多個表深度修改、存儲過程調用、特定數據庫特性),直接使用 QSqlQuery結合自定義模型 (QAbstractItemModel) 可能是更靈活的選擇。
??4、委托:?? QSqlRelationalDelegate對于關系列的編輯體驗至關重要。你也可以創建自定義委托來實現更復雜的關系編輯邏輯。
本次分享就到這里了,如果有什么錯誤的話請指正,或者有什么疑問的,也可以在評論區一起探討!