C++ Qt开发:TableView与TreeView组件联动
Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程序,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹TableView與TreeView組件聯動的常用方法及靈活運用。
本章我們繼續實現表格的聯動效果,當讀者點擊TableView或TreeView中的某一行時,我們讓其實現自動跟隨功能,且當用戶修改行中特定數據時也讓其動態的跟隨改變,首先繪制一個主界面如圖,分別放置兩個組件框,底部保留兩個按鈕,按鈕1用于該表表格的行列個數,按鈕2則用于設置TableView表格表頭參數,整個表格我們將其設置為可編輯狀態。
在函數中我們需要定義一個QStandardItemModel模型,這個模型的作用在之前的文章中有具體介紹,它是一個靈活且功能強大的模型類,適用于需要自定義數據結構、支持編輯、表頭等功能的場景。通常用于與視圖組件(如 QTableView、QTreeView 等)一起使用。它提供了一個表格結構,可以包含行和列,每個單元格可以存儲一個 QStandardItem 對象。
這里的QStandardItemModel只適用于將兩個不同類型的組件進行關聯,簡單點來說就是將兩個組件指向同一個數據容器內,這樣當用戶修改任意一個組件內的數據另一個組件也會同步發生變更,但要想實現聯動則還需要使用QItemSelectionModel模型,它負責跟蹤哪些項被選中,以及在模型中項的選擇狀態發生變化時發出信號。
以下是 QItemSelectionModel 的一些重要特性和方法:
- 選擇項: 負責管理模型中的項的選擇狀態,可以單獨選擇項、選定范圍內的項或清除所有選擇項。
-
信號: 當選擇狀態發生變化時,
QItemSelectionModel會發出相應的信號,如selectionChanged信號。 -
選擇模式: 提供多種選擇模式,包括單選、多選、擴展選擇等,可通過設置
SelectionMode進行配置。 -
選擇策略: 提供多種選擇策略,用于定義選擇行為,如
SelectItems、SelectRows、SelectColumns等。 -
與視圖的集成: 通常與
QTableView、QTreeView等視圖組件結合使用,以實現對視圖中項的選擇操作。
該組件是實現模型-視圖架構中選擇的關鍵組件。通過它,可以輕松管理和操作模型中的項的選擇狀態,實現各種靈活的用戶交互。下面是 QItemSelectionModel 類的一些主要方法:
| 方法 | 描述 |
|---|---|
QItemSelectionModel(QAbstractItemModel *model, QObject *parent = nullptr) |
構造函數,創建一個與指定模型關聯的 QItemSelectionModel 對象。 |
QModelIndexList selectedIndexes() const |
獲取當前被選中的項的索引列表。 |
void clear() |
清除所有的選擇項。 |
void setSelectionMode(QItemSelectionModel::SelectionFlags mode) |
設置選擇模式,可以選擇多個項、單個項等。 |
void setSelectionBehavior(QItemSelectionModel::SelectionBehavior behavior) |
設置選擇策略,如選擇單個項、選擇整行、選擇整列等。 |
void select(const QModelIndex &topLeft, const QModelIndex &bottomRight, QItemSelectionModel::SelectionFlags command) |
在指定范圍內進行選擇操作,使用 SelectionFlags 定義選擇操作。 |
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) |
當選擇狀態發生變化時發出的信號,可以通過連接這個信號來處理選擇狀態變化的事件。 |
bool hasSelection() const |
判斷是否有選中的項。 |
上述方法提供了管理選擇項的一些基本操作,包括清除選擇、獲取選中項的索引、設置選擇模式和策略,以及在指定范圍內進行選擇操作。
在MainWindow構造函數中,我們以此執行如下關鍵部分,來實現對主界面的初始化工作;
創建模型和選擇模型
首先創建一個包含4行5列的 QStandardItemModel 模型,并為其創建了一個 QItemSelectionModel 選擇模型。
model = new QStandardItemModel(4, 5, this);
selection = new QItemSelectionModel(model);
關聯到 tableView 和 treeView
將模型和選擇模型關聯到 tableView 和 treeView 上,這樣它們會共享同一份數據模型,也就是無論兩個組件哪一個發生變化均會影響雙方組件中的內容。
ui->tableView->setModel(model);
ui->tableView->setSelectionModel(selection);
ui->treeView->setModel(model);
ui->treeView->setSelectionModel(selection);
添加表頭與初始化數據
創建一個包含列名的 HeaderList 字符串列表,并將其設置為模型的水平表頭標簽。繼續創建一個包含三個字符串列表的數組 DataList,每個列表代表一行數據。然后使用嵌套的循環遍歷數組,將數據逐個添加到模型中。
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" << "女" << "是";
通過循環添加數據到模型
使用兩個循環,外層循環遍歷數組,內層循環遍歷每個數組中的元素,創建 QStandardItem 對象并將其添加到模型的相應位置。
cppCopy codeint Array_Length = DataList->length(); // 獲取每個數組中元素數
int Array_Count = sizeof(DataList) / sizeof(DataList[0]); // 獲取數組個數
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);
}
}
如上這段代碼初始化了一個包含表頭和數據的 QStandardItemModel 模型,然后將模型和選擇模型關聯到 tableView 和 treeView 上,最后通過循環將數據逐個添加到模型中。這樣就創建了一個主窗口,其中包含了一個表格視圖和一個樹形視圖,它們共享相同的數據模型。如下圖所示;
DialogSize.ui
接著來看on_pushButton_clicked按鈕是如何實現的,該按鈕主要用于實現改變表格行與列,當點擊后則會彈出一個DialogSize自定義對話框,至于對話框是如何添加的在之前的文章中已經詳細介紹過了。
在如下代碼中我們通過model->rowCount()以及model->columnCount()獲取到父UI界面中tableView表格的行列數,并通過ptr->setRowColumn將這些數據設置到了子對話框的編輯框上面,而ptr->columnCount()則用于接收子對話框的返回值,并將其動態設置到對應的模型中;
void MainWindow::on_pushButton_clicked()
{
// //模態對話框,動態創建,用過后刪除
DialogSize *ptr = new DialogSize(this); // 創建一個對話框
Qt::WindowFlags flags = ptr->windowFlags(); // 需要獲取返回值
ptr->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); // 設置對話框固定大小
ptr->setRowColumn(model->rowCount(),model->columnCount()); // 對話框數據初始化
int ref = ptr->exec(); // 以模態方式顯示對話框
if (ref==QDialog::Accepted) // OK鍵被按下,對話框關閉
{
// 當BtnOk被按下時,則設置對話框中的數據
int cols=ptr->columnCount();
model->setColumnCount(cols);
int rows=ptr->rowCount();
model->setRowCount(rows);
}
// 最后刪除釋放對話框句柄
delete ptr;
}
接著來看下子對話框DialogSize做了什么,在對話框代碼中rowCount()是給主窗體調用的函數其功能是獲取到當前對話框中spinBoxRow組件中的數值,而columnCount()同理用于得到spinBoxColumn組件中的數值,最后的setRowColumn()則是用于接收主窗體的船只,并設置到對應的子對話框上的SpinBox組件內,其代碼如下;
DialogSize::DialogSize(QWidget *parent) :QDialog(parent),ui(new Ui::DialogSize)
{
ui->setupUi(this);
}
DialogSize::~DialogSize()
{
delete ui;
}
// 主窗體調用獲取當前行數
int DialogSize::rowCount()
{
return ui->spinBoxRow->value();
}
// 主窗體調用獲取當前列數
int DialogSize::columnCount()
{
return ui->spinBoxColumn->value();
}
// 設置主窗體中的TableView行數與列數
void DialogSize::setRowColumn(int row, int column)
{
ui->spinBoxRow->setValue(row);
ui->spinBoxColumn->setValue(column);
}
運行程序,并點擊左側第一個按鈕,此時我們可以將表格設置為6*6的矩陣,如下圖所示;
DIalogHead.ui
對于第二個按鈕on_pushButton_2_clicked的功能實現與第一個按鈕完全一致,該按鈕主要實現對父窗體中TableView的表頭進行重新設置,在彈出對話框之前,需要將當前表頭元素復制到strList列表容器內,并通過使用子對話框中的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);
// 如果表頭列數變化,則從新初始化
if(ptr->headerList().count() != model->columnCount())
{
QStringList strList;
// 獲取現有的表頭標題
for (int i=0;i<model->columnCount();i++)
{
strList.append(model->headerData(i,Qt::Horizontal,Qt::DisplayRole).toString());
}
// 用于對話框初始化顯示
ptr->setHeaderList(strList);
}
// 調用彈窗
int ref = ptr->exec();
if(ref==QDialog::Accepted)
{
// 獲取對話框上修改后的StringList
QStringList strList=ptr->headerList();
// 設置模型的表頭標題
model->setHorizontalHeaderLabels(strList);
}
delete ptr;
}
當讀者按下了修改按鈕之后,由于通過ui->listView->setModel(model)已經與父窗體建立了關聯,則此時通過model->setStringList(headers)就可以實現對父窗體中數據的修改,代碼如下所示;
DialogHead::DialogHead(QWidget *parent) :QDialog(parent),ui(new Ui::DialogHead)
{
ui->setupUi(this);
model = new QStringListModel;
ui->listView->setModel(model);
}
DialogHead::~DialogHead()
{
delete ui;
}
// 設置當前listView中的數據
void DialogHead::setHeaderList(QStringList &headers)
{
model->setStringList(headers);
}
// 返回當前的表頭
QStringList DialogHead::headerList()
{
return model->stringList();
}
程序運行后,讀者可以先將表格的行與列修改為7*7,接著再通過設置表頭的方式更新表頭,效果如下;
總結
以上是生活随笔為你收集整理的C++ Qt开发:TableView与TreeView组件联动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: dnf心悦特邀会员怎么获得(地下城与勇士
- 下一篇: 2023-12-27:用go语言,店铺数