Qt中TableView與TreeView組件聯(lián)動實(shí)現(xiàn)
Qt 是一個跨平臺C++圖形界面開發(fā)庫,利用Qt可以快速開發(fā)跨平臺窗體應(yīng)用程序,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實(shí)現(xiàn)圖形化開發(fā)極大的方便了開發(fā)效率,本章將重點(diǎn)介紹TableView
與TreeView
組件聯(lián)動的常用方法及靈活運(yùn)用。
本章我們繼續(xù)實(shí)現(xiàn)表格的聯(lián)動效果,當(dāng)讀者點(diǎn)擊TableView
或TreeView
中的某一行時(shí),我們讓其實(shí)現(xiàn)自動跟隨功能,且當(dāng)用戶修改行中特定數(shù)據(jù)時(shí)也讓其動態(tài)的跟隨改變,首先繪制一個主界面如圖,分別放置兩個組件框,底部保留兩個按鈕,按鈕1用于該表表格的行列個數(shù),按鈕2則用于設(shè)置TableView
表格表頭參數(shù),整個表格我們將其設(shè)置為可編輯狀態(tài)。
在函數(shù)中我們需要定義一個QStandardItemModel
模型,這個模型的作用在之前的文章中有具體介紹,它是一個靈活且功能強(qiáng)大的模型類,適用于需要自定義數(shù)據(jù)結(jié)構(gòu)、支持編輯、表頭等功能的場景。通常用于與視圖組件(如 QTableView
、QTreeView
等)一起使用。它提供了一個表格結(jié)構(gòu),可以包含行和列,每個單元格可以存儲一個 QStandardItem
對象。
這里的QStandardItemModel
只適用于將兩個不同類型的組件進(jìn)行關(guān)聯(lián),簡單點(diǎn)來說就是將兩個組件指向同一個數(shù)據(jù)容器內(nèi),這樣當(dāng)用戶修改任意一個組件內(nèi)的數(shù)據(jù)另一個組件也會同步發(fā)生變更,但要想實(shí)現(xiàn)聯(lián)動則還需要使用QItemSelectionModel
模型,它負(fù)責(zé)跟蹤哪些項(xiàng)被選中,以及在模型中項(xiàng)的選擇狀態(tài)發(fā)生變化時(shí)發(fā)出信號。
以下是 QItemSelectionModel
的一些重要特性和方法:
- 選擇項(xiàng): 負(fù)責(zé)管理模型中的項(xiàng)的選擇狀態(tài),可以單獨(dú)選擇項(xiàng)、選定范圍內(nèi)的項(xiàng)或清除所有選擇項(xiàng)。
- 信號: 當(dāng)選擇狀態(tài)發(fā)生變化時(shí),
QItemSelectionModel
會發(fā)出相應(yīng)的信號,如selectionChanged
信號。 - 選擇模式: 提供多種選擇模式,包括單選、多選、擴(kuò)展選擇等,可通過設(shè)置
SelectionMode
進(jìn)行配置。 - 選擇策略: 提供多種選擇策略,用于定義選擇行為,如
SelectItems
、SelectRows
、SelectColumns
等。 - 與視圖的集成: 通常與
QTableView
、QTreeView
等視圖組件結(jié)合使用,以實(shí)現(xiàn)對視圖中項(xiàng)的選擇操作。
該組件是實(shí)現(xiàn)模型-視圖架構(gòu)中選擇的關(guān)鍵組件。通過它,可以輕松管理和操作模型中的項(xiàng)的選擇狀態(tài),實(shí)現(xiàn)各種靈活的用戶交互。下面是 QItemSelectionModel
類的一些主要方法:
方法 | 描述 |
---|---|
QItemSelectionModel(QAbstractItemModel *model, QObject *parent = nullptr) | 構(gòu)造函數(shù),創(chuàng)建一個與指定模型關(guān)聯(lián)的 QItemSelectionModel 對象。 |
QModelIndexList selectedIndexes() const | 獲取當(dāng)前被選中的項(xiàng)的索引列表。 |
void clear() | 清除所有的選擇項(xiàng)。 |
void setSelectionMode(QItemSelectionModel::SelectionFlags mode) | 設(shè)置選擇模式,可以選擇多個項(xiàng)、單個項(xiàng)等。 |
void setSelectionBehavior(QItemSelectionModel::SelectionBehavior behavior) | 設(shè)置選擇策略,如選擇單個項(xiàng)、選擇整行、選擇整列等。 |
void select(const QModelIndex &topLeft, const QModelIndex &bottomRight, QItemSelectionModel::SelectionFlags command) | 在指定范圍內(nèi)進(jìn)行選擇操作,使用 SelectionFlags 定義選擇操作。 |
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) | 當(dāng)選擇狀態(tài)發(fā)生變化時(shí)發(fā)出的信號,可以通過連接這個信號來處理選擇狀態(tài)變化的事件。 |
bool hasSelection() const | 判斷是否有選中的項(xiàng)。 |
上述方法提供了管理選擇項(xiàng)的一些基本操作,包括清除選擇、獲取選中項(xiàng)的索引、設(shè)置選擇模式和策略,以及在指定范圍內(nèi)進(jìn)行選擇操作。
在MainWindow
構(gòu)造函數(shù)中,我們以此執(zhí)行如下關(guān)鍵部分,來實(shí)現(xiàn)對主界面的初始化工作;
創(chuàng)建模型和選擇模型
首先創(chuàng)建一個包含4行5列的 QStandardItemModel
模型,并為其創(chuàng)建了一個 QItemSelectionModel
選擇模型。
model = new QStandardItemModel(4, 5, this); selection = new QItemSelectionModel(model);
關(guān)聯(lián)到 tableView
和 treeView
將模型和選擇模型關(guān)聯(lián)到 tableView
和 treeView
上,這樣它們會共享同一份數(shù)據(jù)模型,也就是無論兩個組件哪一個發(fā)生變化均會影響雙方組件中的內(nèi)容。
ui->tableView->setModel(model); ui->tableView->setSelectionModel(selection); ui->treeView->setModel(model); ui->treeView->setSelectionModel(selection);
添加表頭與初始化數(shù)據(jù)
創(chuàng)建一個包含列名的 HeaderList
字符串列表,并將其設(shè)置為模型的水平表頭標(biāo)簽。繼續(xù)創(chuàng)建一個包含三個字符串列表的數(shù)組 DataList
,每個列表代表一行數(shù)據(jù)。然后使用嵌套的循環(huán)遍歷數(shù)組,將數(shù)據(jù)逐個添加到模型中。
QStringList HeaderList; HeaderList << "序號" << "姓名" << "年齡" << "性別" << "婚否"; model->setHorizontalHeaderLabels(HeaderList); QStringList DataList[3]; QStandardItem *Item; DataList[0] << "1001" << "admin" << "24" << "男" << "是"; DataList[1] << "1002" << "lyshark" << "23" << "男" << "否"; DataList[2] << "1003" << "lucy" << "37" << "女" << "是";
通過循環(huán)添加數(shù)據(jù)到模型
使用兩個循環(huán),外層循環(huán)遍歷數(shù)組,內(nèi)層循環(huán)遍歷每個數(shù)組中的元素,創(chuàng)建 QStandardItem
對象并將其添加到模型的相應(yīng)位置。
int Array_Length = DataList->length(); // 獲取每個數(shù)組中元素?cái)?shù) int Array_Count = sizeof(DataList) / sizeof(DataList[0]); // 獲取數(shù)組個數(shù) for(int x=0; x<Array_Count; x++) { for(int y=0; y<Array_Length; y++) { Item = new QStandardItem(DataList[x][y]); model->setItem(x, y, Item); } }
如上這段代碼初始化了一個包含表頭和數(shù)據(jù)的 QStandardItemModel
模型,然后將模型和選擇模型關(guān)聯(lián)到 tableView
和 treeView
上,最后通過循環(huán)將數(shù)據(jù)逐個添加到模型中。這樣就創(chuàng)建了一個主窗口,其中包含了一個表格視圖和一個樹形視圖,它們共享相同的數(shù)據(jù)模型。如下圖所示;
DialogSize.ui
接著來看on_pushButton_clicked
按鈕是如何實(shí)現(xiàn)的,該按鈕主要用于實(shí)現(xiàn)改變表格行與列,當(dāng)點(diǎn)擊后則會彈出一個DialogSize
自定義對話框,至于對話框是如何添加的在之前的文章中已經(jīng)詳細(xì)介紹過了。
在如下代碼中我們通過model->rowCount()
以及model->columnCount()
獲取到父UI
界面中tableView
表格的行列數(shù),并通過ptr->setRowColumn
將這些數(shù)據(jù)設(shè)置到了子對話框的編輯框上面,而ptr->columnCount()
則用于接收子對話框的返回值,并將其動態(tài)設(shè)置到對應(yīng)的模型中;
void MainWindow::on_pushButton_clicked() { // //模態(tài)對話框,動態(tài)創(chuàng)建,用過后刪除 DialogSize *ptr = new DialogSize(this); // 創(chuàng)建一個對話框 Qt::WindowFlags flags = ptr->windowFlags(); // 需要獲取返回值 ptr->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); // 設(shè)置對話框固定大小 ptr->setRowColumn(model->rowCount(),model->columnCount()); // 對話框數(shù)據(jù)初始化 int ref = ptr->exec(); // 以模態(tài)方式顯示對話框 if (ref==QDialog::Accepted) // OK鍵被按下,對話框關(guān)閉 { // 當(dāng)BtnOk被按下時(shí),則設(shè)置對話框中的數(shù)據(jù) int cols=ptr->columnCount(); model->setColumnCount(cols); int rows=ptr->rowCount(); model->setRowCount(rows); } // 最后刪除釋放對話框句柄 delete ptr; }
接著來看下子對話框DialogSize
做了什么,在對話框代碼中rowCount()
是給主窗體調(diào)用的函數(shù)其功能是獲取到當(dāng)前對話框中spinBoxRow
組件中的數(shù)值,而columnCount()
同理用于得到spinBoxColumn
組件中的數(shù)值,最后的setRowColumn()
則是用于接收主窗體的船只,并設(shè)置到對應(yīng)的子對話框上的SpinBox
組件內(nèi),其代碼如下;
DialogSize::DialogSize(QWidget *parent) :QDialog(parent),ui(new Ui::DialogSize) { ui->setupUi(this); } DialogSize::~DialogSize() { delete ui; } // 主窗體調(diào)用獲取當(dāng)前行數(shù) int DialogSize::rowCount() { return ui->spinBoxRow->value(); } // 主窗體調(diào)用獲取當(dāng)前列數(shù) int DialogSize::columnCount() { return ui->spinBoxColumn->value(); } // 設(shè)置主窗體中的TableView行數(shù)與列數(shù) void DialogSize::setRowColumn(int row, int column) { ui->spinBoxRow->setValue(row); ui->spinBoxColumn->setValue(column); }
運(yùn)行程序,并點(diǎn)擊左側(cè)第一個按鈕,此時(shí)我們可以將表格設(shè)置為6*6
的矩陣,如下圖所示;
DIalogHead.ui
對于第二個按鈕on_pushButton_2_clicked
的功能實(shí)現(xiàn)與第一個按鈕完全一致,該按鈕主要實(shí)現(xiàn)對父窗體中TableView
的表頭進(jìn)行重新設(shè)置,在彈出對話框之前,需要將當(dāng)前表頭元素復(fù)制到strList
列表容器內(nèi),并通過使用子對話框中的ptr->setHeaderList
將其拷貝到子對話框中,并通過QDialog::Accepted
等待對話框按下修改按鈕,如下代碼所示;
void MainWindow::on_pushButton_2_clicked() { DialogHead *ptr = new DialogHead(this); Qt::WindowFlags flags = ptr->windowFlags(); ptr->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); // 如果表頭列數(shù)變化,則從新初始化 if(ptr->headerList().count() != model->columnCount()) { QStringList strList; // 獲取現(xiàn)有的表頭標(biāo)題 for (int i=0;i<model->columnCount();i++) { strList.append(model->headerData(i,Qt::Horizontal,Qt::DisplayRole).toString()); } // 用于對話框初始化顯示 ptr->setHeaderList(strList); } // 調(diào)用彈窗 int ref = ptr->exec(); if(ref==QDialog::Accepted) { // 獲取對話框上修改后的StringList QStringList strList=ptr->headerList(); // 設(shè)置模型的表頭標(biāo)題 model->setHorizontalHeaderLabels(strList); } delete ptr; }
當(dāng)讀者按下了修改按鈕之后,由于通過ui->listView->setModel(model)
已經(jīng)與父窗體建立了關(guān)聯(lián),則此時(shí)通過model->setStringList(headers)
就可以實(shí)現(xiàn)對父窗體中數(shù)據(jù)的修改,代碼如下所示;
DialogHead::DialogHead(QWidget *parent) :QDialog(parent),ui(new Ui::DialogHead) { ui->setupUi(this); model = new QStringListModel; ui->listView->setModel(model); } DialogHead::~DialogHead() { delete ui; } // 設(shè)置當(dāng)前l(fā)istView中的數(shù)據(jù) void DialogHead::setHeaderList(QStringList &headers) { model->setStringList(headers); } // 返回當(dāng)前的表頭 QStringList DialogHead::headerList() { return model->stringList(); }
程序運(yùn)行后,讀者可以先將表格的行與列修改為7*7
,接著再通過設(shè)置表頭的方式更新表頭,效果如下;
到此這篇關(guān)于Qt中TableView與TreeView組件聯(lián)動實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Qt TableView與TreeView聯(lián)動內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Qt GUI圖形圖像開發(fā)之QT表格控件QTableView,QTableWidget復(fù)雜表頭(多行表頭) 及凍結(jié)、固定特定的行的詳細(xì)方法與實(shí)例
- Qt GUI圖形圖像開發(fā)之Qt表格控件QTableView簡單使用方法及QTableView與QTableWidget區(qū)別
- Qt GUI圖形圖像開發(fā)之QT表格控件QTableView詳細(xì)使用方法與實(shí)例
- C/C++?Qt?數(shù)據(jù)庫與TableView實(shí)現(xiàn)多組件聯(lián)動
- Qt實(shí)現(xiàn)導(dǎo)出QTableWidget/QTableView數(shù)據(jù)
- C++中的Qt?QTableView詳解
相關(guān)文章
LeetCode題解C++生成每種字符都是奇數(shù)個的字符串
這篇文章主要為大家介紹了LeetCode題解C++生成每種字符都是奇數(shù)個的字符串示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10C語言實(shí)現(xiàn)字符串轉(zhuǎn)浮點(diǎn)函數(shù)的示例
字符串不僅可以轉(zhuǎn)換為整數(shù),也可以轉(zhuǎn)換為浮點(diǎn)數(shù),本文主要介紹了C語言實(shí)現(xiàn)字符串轉(zhuǎn)浮點(diǎn)函數(shù)的示例,具有一定的參考價(jià)值,感興趣的可以了解一下2022-02-02與ASCII碼相關(guān)的C語言字符串操作函數(shù)
這篇文章主要介紹了與ASCII碼相關(guān)的C語言字符串操作函數(shù),分別是將字符轉(zhuǎn)換為ASCII碼的toascii()函數(shù)和根據(jù)ASCII碼進(jìn)行字符串比較的strcoll()函數(shù),需要的朋友可以參考下2015-08-08