每日激勵:“不設限和自我肯定的心態:I can do all things。 — Stephen Curry”
緒論?:
本章將通過代碼示例詳細介紹了Qt中QListWidget、QTableWidget和QTreeWidget三種多元素控件的使用方法與核心功能,涵蓋列表的增刪操作、表格的行列管理以及樹形結構的節點處理。
————————
早關注不迷路,話不多說安全帶系好,發車啦(建議電腦觀看)。
多元素控件
Qt 中提供的多元素控件有:
- QListWidget
- QListView(前兩個表示列表結構)
- QTableWidget
- QTableView(前兩個表示表格結構)
- QTreeWidget
- QTreeView(前兩個表示樹形結構)
不難發現兩種結構中有:xxWidget 和 xxView 之間的區別
- xxView 是更底層的實現
- xxWidget 是基于 xxView 封裝起來的
例如:
- QTableView 是基于 MVC 設計的控件
- QTableView ??不持有數據(不支持Model)。使? QTableView 的時候需要??創建?個 Model 對象 (?如 QStandardModel ),比較麻煩~
- 并且把 Model 和 QTableView 關聯起來. 后續修改 Model 中的數據就會影響 QTableView 的顯?
- 修改 QTableView 的顯?也會影響到 Model 中的數據(雙向綁定).
- QTableWidget 則是 QTableView 的?類, 對 Model 進?了封裝
- 所以不需要???動創建 Model 對象, 直接就可以往 QTableWidget 中添加數據了
- 提供了更方便的 api 讓自己使用
不能說誰好誰壞,不同場景使用不同:
- 其中 xxxWidget 使用起來比較方便,但功能有限
- 而 xxxView 使用起來比較麻煩,但可以自由diy,實現更復雜的功能
因為他們是兩兩一組的,所以此處就著重講解Widget
List Widget 多元素控件 列表
使? QListWidget 能夠顯??個縱向的列表. 形如:
核?屬性
屬性 | 說明 |
---|---|
currentRow | 當前被選中的是第?? |
count | ?共有多少? |
sortingEnabled | 是否允許排序 |
isWrapping | 是否允許換? |
itemAlignment | 元素的對??式 |
selectRectVisible | 被選中的元素矩形(高亮)是否可? |
spacing | 元素之間的間隔 |
核??法
?法 | 說明 |
---|---|
addItem(const QString& label) addItem(QListWidgetItem *item) | 列表中添加元素(列表中的每個元素/每一項就成為一個item(通過QListWidgetItem 類表示)) |
currentItem() | 返回 QListWidgetItem* 表?當前選中的元素 |
setCurrentItem(QListWidgetItem* item) | 設置選中哪個元素 |
setCurrentRow(int row) | 設置選中第??的元素 |
insertItem(const QString& label, int row) insertItem(QListWidgetItem *item, int row) | 在指定的位置插?元素 (此處的 row 參數就表示插入完畢之后新的元素在第幾行,也就是把新元素插入到第幾行之前) |
item(int row) | 返回 QListWidgetItem* 表?第 row ?的元素 |
takeItem(int row) | 刪除指定?的元素, 返回 QListWidgetItem* 表?是哪個元素被刪除了 |
核?信號
?法 | 說明 |
---|---|
currentItemChanged(QListWidgetItem* current, QListWidgetItem* old) | 選中不同元素時會觸發. 參數是當前選中的元素和之前選中的元素. |
currentRowChanged(int) | 選中不同元素時會觸發. 參數是當前選中元素的?數. |
itemClicked(QListWidgetItem* item) | 點擊某個元素時觸發 |
itemDoubleClicked(QListWidgetItem* item) | 雙擊某個元素時觸發 |
itemEntered(QListWidgetItem* item) | ?標進?元素時觸發 |
當選錯了多元素控件的時候,可以通過右鍵選擇 “變型為” 進行修改:
實操:ListWidget的新增刪除列表
-
初始化默認的值
- 直接在構造函數中
- 通過列表控件調用addItem接口
- 添加:C++、Java、Python 子元素
- 也能直接在圖形化界面中的右擊 “列表控件” 選擇 “編輯項目” 進行添加
- 直接在構造函數中
-
給新增按鈕添加點擊信號的槽函數:
- 獲取到輸入框中的內容
- 將獲取到的內容 添加到QListWidget中
-
給刪除按鈕添加點擊信號的槽函數:
- 獲取被選元素它的行號(
currentRow
) - 按行號進行刪除元素
takeitem
- 獲取被選元素它的行號(
-
右鍵列表新增
currentItemChanged
信號的槽函數(需要添加頭文件 QListWidgetItem):- 通過這個槽函數感知變化
- 判斷current是否為空,不為空則打印:當前選中元素的文本
- 并且判斷 previous 不為空的話也進行打印文本
結果:
源碼:
#include "widget.h"
#include "ui_widget.h"#include <QListWidget>
#include <QDebug>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//添加子元素 addItemui->listWidget->addItem("C++");ui->listWidget->addItem("Java");ui->listWidget->addItem("Python");
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{//獲取label內部的數據QString text = ui->lineEdit->text();//添加到list中ui->listWidget->addItem(text);
}void Widget::on_pushButton_2_clicked()
{//獲取鼠標選中的行號int row = ui->listWidget->currentRow();//刪除行號的內容 takeitemui->listWidget->takeItem(row);
}void Widget::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{if(previous != nullptr){qDebug() << "previous: "<< previous->text();}//current 表示當前選中的元素、previous表示選中這個元素之前選擇的元素if(current != nullptr){qDebug() << "current: "<< current->text();}}
Table Widget
使? QTableWidget 表??個表格控件. ?個表格中包含若??, 每???包含若?列. 表格中的每個單元格, 是?個 QTableWidgetItem 對象
QTableWidget 核??法
?法 | 說明 |
---|---|
item(int row, int column) | 根據?數列數獲取指定的 QTableWidgetItem* |
setItem(int row, int column, QTableWidget*) | 根據?數列數設置表格中的元素 |
currentItem() | 返回被選中的元素 QTableWidgetItem* |
currentRow() | 返回被選中元素是第?? |
currentColumn() | 返回被選中元素是第?列 |
row(QTableWidgetItem* ) | 獲取指定 item 是第?? |
column(QTableWidgetItem* ) | 獲取指定 item 是第?列 |
rowCount() | 獲取?數 |
columnCount() | 獲取列數 |
insertRow(int row) | 在第 row ?處插?新? |
insertColumn(int column) | 在第 column 列插?新列 |
removeRow(int row) | 刪除第 row ? |
removeColumn(int column) | 刪除第 column 列 |
setHorizontalHeaderItem(int column, QTableWidget*) | 設置指定列的表頭 |
setVerticalHeaderItem(int row, QTableWidget*) | 設置指定?的表頭 |
QTableWidgetItem 核?信號
信號 | 說明 |
---|---|
cellClicked(int row, int column) | 點擊單元格時觸發 |
cellDoubleClicked(int row, int column) | 雙擊單元格時觸發 |
cellEntered(int row, int column) | ?標進?單元格時觸發 |
currentCellChanged(int row, int column, int previousRow, int previousColumn) | 選中不同單元格時觸發 |
QTableWidgetItem 核?方法
?法 | 說明 |
---|---|
row() | 獲取當前是第?? |
column() | 獲取當前是第?列 |
setText(const QString&) | 設置?本 |
setTextAlignment(int) | 設置?本對? |
setIcon(const QIcon&) | 設置圖標 |
setSelected(bool) | 設置被選中 |
setSizeHints(const QSize&) | 設置尺? |
setFont(const QFont&) | 設置字體 |
實操:簡單實現表格增加行/列,添加元素
-
使用ui構建,如上圖
-
編輯框初始化:
- 新增列:學號、姓名、年齡
- 新增行:1、2、3
- 1 張三 20、…
-
代碼初始化:
- 創建三行(
insertRow
) - 創建三列(
insertColumn
) - 給3個列設定列名:
setHeorizontalHeaderItem
- 給表格中添加數據
setItem
(行,列,QTableWidgetItem(數據))
- 創建三行(
初始化的值:
給按鈕添加槽函數:
- 給新增一行按鈕添加槽函數
- 獲取多少行
rowCount
- 在最后一行之后新增新行
insertRow(rowCount)
(注意此處是下標,表示你新增之后的這是第幾行)
- 獲取多少行
- 刪除選中行
- 獲取選中的行號
currentRow
- 刪除這一行
removeRow
- 獲取選中的行號
- 新增行
- 獲取有幾列
columnCount
- 新增一列
insertColumn
- 設置列名(從輸入框中獲取)
- 獲取輸入框的文本
- 給新增行添加列名
setHorizontalHeaderItem
- 獲取有幾列
- 刪除選中列
- 獲取選中列號
currentColumn
- 刪除這一列
removeColumn
- 獲取選中列號
源碼:
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//新增行ui->tableWidget_2->insertRow(0);//默認的即可不用設置行名稱ui->tableWidget_2->insertRow(1);ui->tableWidget_2->insertRow(2);//新增列ui->tableWidget_2->insertColumn(0);ui->tableWidget_2->setHorizontalHeaderItem(0,new QTableWidgetItem("學號"));ui->tableWidget_2->insertColumn(1);ui->tableWidget_2->setHorizontalHeaderItem(1,new QTableWidgetItem("姓名"));ui->tableWidget_2->insertColumn(2);ui->tableWidget_2->setHorizontalHeaderItem(2,new QTableWidgetItem("年齡"));//添加數據ui->tableWidget_2->setItem(0,0,new QTableWidgetItem("1"));ui->tableWidget_2->setItem(0,1,new QTableWidgetItem("張三"));ui->tableWidget_2->setItem(0,2,new QTableWidgetItem("20"));ui->tableWidget_2->setItem(1,0,new QTableWidgetItem("2"));ui->tableWidget_2->setItem(1,1,new QTableWidgetItem("李四"));ui->tableWidget_2->setItem(1,2,new QTableWidgetItem("28"));ui->tableWidget_2->setItem(2,0,new QTableWidgetItem("3"));ui->tableWidget_2->setItem(2,1,new QTableWidgetItem("王五"));ui->tableWidget_2->setItem(2,2,new QTableWidgetItem("88"));}Widget::~Widget()
{delete ui;
}//新增一列
void Widget::on_pushButton_clicked()
{//獲取LineEdit中的文本QString text = ui->lineEdit->text();//獲取當前列數int ccount = ui->tableWidget->columnCount();//添加新列ui->tableWidget->insertColumn(ccount);//添加的是下標,所以剛好和個數相同//添加列名稱if(text != nullptr){ui->tableWidget->setHorizontalHeaderItem(ccount,new QTableWidgetItem(text));}
}//刪除選擇的列
void Widget::on_pushButton_2_clicked()
{//獲取光標選中的列int ccolumn = ui->tableWidget->currentColumn();//刪除ui->tableWidget->removeColumn(ccolumn);
}//新增一行
void Widget::on_pushButton_3_clicked()
{//獲取LineEdit中的文本QString text = ui->lineEdit->text();//獲取當前行數int rcount = ui->tableWidget->rowCount();//添加新行ui->tableWidget->insertRow(rcount);//添加的是下標,所以剛好和個數相同//添加行名稱if(text != ""){ui->tableWidget->setVerticalHeaderItem(rcount,new QTableWidgetItem(text));}
}//刪除選中的行
void Widget::on_pushButton_4_clicked()
{//獲取光標選中的行int crow = ui->tableWidget->currentRow();//刪除行ui->tableWidget->removeRow(crow);
}
Tree Widget
使? QTreeWidget 表??個樹形控件。??的每個元素, 都是?個 QTreeWidgetItem ,每個
QTreeWidgetItem 可以包含多個?本和圖標,每個?本/圖標為?個 列。可以給 QTreeWidget 設置頂層節點(頂層節點可以有多個), 然后再給頂層節點添加?節點, 從?構成樹形結構。
對于列數的使用,可以對某子元素進行數據的展示,例如下圖的 貓2 列,可以改成貓的年齡/體重,來描述當前子元素的各種屬性數據
QTreeWidget 的 核??法(頂層結點的方法)
?法 | 說明 |
---|---|
clear | 清空所有?節點 |
addTopLevelItem(QTreeWidgetItem* item) | 新增頂層節點 |
topLevelItem(int index) | 獲取指定下標的頂層節點. |
topLevelItemCount() | 獲取頂層節點個數 |
indexOfTopLevelItem(QTreeWidgetItem* item) | 查詢指定節點是頂層節點中的下標 |
takeTopLevelItem(int index) | 刪除指定的頂層節點. 返回 QTreeWidgetItem* 表?被刪除的元素 |
currentItem() | 獲取到當前選中的節點, 返回 QTreeWidgetItem* |
setCurrentItem(QTreeWidgetItem* item) | 選中指定節點 |
setExpanded(bool) | 控制 展開/關閉 子節點 |
setHeaderLabel(const QString& text) | 設置 TreeWidget 的 header 名稱 |
其中QTreeWidget控件雖然是樹形結構,但是這個樹形結構沒有根節點,是從根結點的下一層結點開始計算的(如下圖),所以是新增頂層結點
QTreeWidget 核?信號
信號 | 說明 |
---|---|
currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* old) | 切換選中元素時觸發 |
itemClicked(QTreeWidgetItem* item, int col) | 點擊元素時觸發 |
itemDoubleClicked(QTreeWidgetItem* item, int col) | 雙擊元素時觸發 |
itemEntered(QTreeWidgetItem* item, int col) | ?標進?時觸發 |
itemExpanded(QTreeWidgetItem* item) | 元素被展開時觸發 |
itemCollapsend(QTreeWidgetItem* item) | 元素被折疊時觸發 |
QTreeWidgetItem 核?屬性
屬性 | 說明 |
---|---|
text | 持有的?本 |
textAlignment | ?本對??式 |
icon | 持有的圖表 |
font | ?本字體 |
hidden | 是否隱藏 |
disabled | 是否禁? |
expand | 是否展開 |
sizeHint | 尺??? |
selected | 是否選中 |
QTreeWidgetItem 核??法(子節點的方法)
?法 | 說明 |
---|---|
addChild(QTreeWidgetItem* child) | 新增?節點 |
childCount() | ?節點的個數 |
child(int index) | 獲取指定下標的?節點. 返回 QTreeWidgetItem* |
takeChild(int index) | 刪除對應下標的?節點 |
removeChild(QTreeWidgetItem* child) | 刪除對應的?節點 |
parent() | 獲取該元素的?節點 |
實操:理解頂層元素和子元素的添加刪除
通過界面編輯快速填充初始值
代碼操作:
- 拖拽一個treeWidget
- 設置根節點的名字
setHeaderLabel
- 新增頂層結點
- 創建
QTreeWidgetItem
結點對象 - 每個結點都可以設置多個列名稱
setText
(列數(從0開始),名稱貓、狗、鳥) - 添加到頂層結點中,
addTopLevelItem
- 創建
- 再添加
貓
的子節點- 寫創建 結點對象,設置名稱(列數,中華田園貓、布偶貓、…)
- 添加到item1中的子節點 addChild
三個按鈕的槽函數
- 插入頂層結點按鈕添加點擊信號的槽函數
- 獲取輸入框中的內容
- 構造一個節點對象,設置名稱
setText
將獲取到的內容給到 - 添加到頂層結點中
- 插入子節點
- 獲取當前選中節點對象 currentItem(若為空則啥也不做返回…)
- 獲取輸入框中的內容
- 構造一個節點對象,
- 設置名稱
setText
將獲取到的內容給到(同上12不變) - 插入到選中結點的子節點中
- 刪除選中的元素
- 獲取選中元素
- 非空則刪除選中元素,需要先獲取父元素,通過父元素進行刪除 parent
- 若為空則代表為頂層元素
- 獲取頂層元素下標
indexOfTopLevelItem
- 從控件中刪除頂層結點,
takeTopLevelItem
- 獲取頂層元素下標
- 非空則為普通元素,則通過獲取的獲取的parent刪除子結點
removeChild
結果:
#include "widget.h"
#include "ui_widget.h"
#include <QTreeWidgetItem>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//設置根節點名稱ui->treeWidget->setHeaderLabel("1");//創建結點對象QTreeWidgetItem* item1 = new QTreeWidgetItem();item1->setText(0,"貓");ui->treeWidget->addTopLevelItem(item1);//給頂層元素添加子元素QTreeWidgetItem* citem1 = new QTreeWidgetItem();citem1->setText(0,"貍花貓");item1->addChild(citem1);//就不多添加了...QTreeWidgetItem* item2 = new QTreeWidgetItem();item2->setText(0, "狗");ui->treeWidget->addTopLevelItem(item2);QTreeWidgetItem* item3 = new QTreeWidgetItem();item3->setText(0, "?");ui->treeWidget->addTopLevelItem(item3);
}Widget::~Widget()
{delete ui;
}//添加頂層元素
void Widget::on_pushButton_clicked()
{//獲取輸入框內容QString text = ui->lineEdit->text();if(text == QString()){text = "默認值...";}//將內容創建項目QTreeWidgetItem* item = new QTreeWidgetItem();item->setText(0,text);//添加到頂層ui->treeWidget->addTopLevelItem(item);
}//添加選中的子元素
void Widget::on_pushButton_2_clicked()
{//獲取當前選中的頂層元素QTreeWidgetItem* item = ui->treeWidget->currentItem();if(item == nullptr) return ;//獲取輸入框內容QString text = ui->lineEdit->text();if(text == QString()){text = "默認值...";}//將輸入框內容添加到創建的新子元素中QTreeWidgetItem* citem = new QTreeWidgetItem();citem->setText(0,text);//給頂層添加新元素item->addChild(citem);
}//刪除選中的節點
void Widget::on_pushButton_3_clicked()
{//獲取當前選中的節點QTreeWidgetItem* item = ui->treeWidget->currentItem();//需要獲取父元素,通過父元素進行刪除QTreeWidgetItem* pitem = item->parent();//若為空則,此時已經是頂層元素if(pitem == nullptr){//獲取指定節點的頂層元素的下標int index = ui->treeWidget->indexOfTopLevelItem(item);ui->treeWidget->takeTopLevelItem(index);}else{ //若不是則://通過獲取的父元素,刪除指定的子元素pitem->removeChild(item);}}
注意上述控件相關的操作,數據都是在內存中的,重新運行程序數據就沒了
本章完。預知后事如何,暫聽下回分解。
如果有任何問題歡迎討論哈!
如果覺得這篇文章對你有所幫助的話點點贊吧!
持續更新大量C++細致內容,早關注不迷路。
?