Qt 專案檢視組(Item Views)與專案控制元件組(Item Widget)
「這是我參與11月更文挑戰的第3天,活動詳情檢視:2021最後一次更文挑戰」。
專案檢視組(Item Views)
專案檢視組如圖所示
專案檢視組各個控制元件名稱解釋:
- List View :清單檢視
- Tree View :樹檢視
- Table View :表檢視
- Column View :列檢視
- Undo View :撤銷列表
首先介紹一下Table View 和 Table Widget的區別
區別如下表
| | | | | ----------------- | ---------------------------- | ------------------------------------------------------- | | 區別 | QTableView | QTableWidget | | 繼承關係 | | QTableWidget繼承自QTableView | | 使用資料模型setModel | 可以使用setModel設定資料模型 | setModel是私有函式,不能使用該函式設定資料模型 | | 顯示覆選框 | 沒有函式實現複選框 | QTableWidgetItem類中的setCheckState (Qt::Checked); 可以設定複選框 | | 與QSqlTableModel繫結 | QTableView能與QSqlTableModel繫結 | QTableWidget不能與QSqlTableModel繫結 |
- 模型:所有的模型都基於QAbstractItemModel類,該類為抽象基類。
- 檢視:所有的檢視都是從QAbstractItemView繼承。
InterView 框架提供了一些常見的模型類和檢視類,如 QStandardItemModel、QDirModel、QStringListModel、QProxyModel和QColumnView、QHeaderView、QListView、QTableView、QTreeView。其中,QDirModel可以通過樹狀方式顯示某個目錄下所有的子目錄以及相關資訊;QProxyModel用於將舊的Model型別過渡到新的型別上;QStandardItemModel使用最簡單的Grid方式顯示Model。而且我們還可以從QAbstractItemModel,QAbstractProxyModel,QAbstractTableModel中繼承出符合自己要求的Model。 慢慢來吧 以後再看。
相對於使用現有的模型和檢視,Qt還提供了更為便捷的類用於處理常見的一些資料模型。他們將模型和檢視合二為一,因此便於處理一些常規的資料結構。使用這些型別雖然簡單方便,但是也失去了模型/檢視結構的靈活性,因此需要見機行事。
QTableWidget繼承自QTableView。QSqlTableModel能夠與QTableView繫結,但是不能和QTableWidget繫結。比如下面這段程式碼
cpp
QSqlTableModel *model = new QSqlTableModel;
model->setTable("employee");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
model->removeColumn(0); // 不顯示ID
model->setHeaderData(0,Qt::Horizontal,tr("name"));
model->setHeaderData(1,Qt::Horizontal,tr("Salary"));
QTableView *view = new QTableView;
view->setModel(model);
view->show();
需要注意得是檢視與模型進行繫結時,模型必須使用new建立,否則檢視不能隨著模型得改變而改變
典型錯誤:
cpp
QStandardItemModel model(4,2);
model.setHeaderData(0,Qt::Horizontal,tr(Label));
model.setHeaderData(1,Qt::Horizontal,tr(Quantity));
ui->tableView->setModel(&model);
for(int row = 0; row < 4; row++)
{
for(int column = 0; column < 2; column++)
{
QModelIndex index = model.index(row,column,QModelIndex());
model.setData(index,QVariant((row+1) * (column+1)));
}
}
正確的寫法應該是這樣的:
cpp
QStandardItemModel *model;
model = new QStandardItemModel(4,2);
model->setHeaderData(0,Qt::Horizontal,tr(Label));
model->setHeaderData(1,Qt::Horizontal,tr(Quantity));
ui->tableView->setModel(model);
for(int row = 0; row < 4; row++)
{
for(int column = 0; column < 2; column++)
{
QModelIndex index = model->index(row,column,QModelIndex());
model->setData(index,QVariant((row+1) * (column+1)));
}
}
專案控制元件組(Item Widgets)
專案控制元件組如圖:
各個控制元件名稱解釋:
- List Widget :清單控制元件
- Tree Widget :樹型控制元件
- Table Widget :表控制元件
例子:
建立一個具有複選框的樹形控制元件。
在Qt中,樹形控制元件稱為QTreeTable,而控制元件裡的樹節點稱為QTreeWidgetItem。這種控制元件有的時候非常有用,比如群發郵件需要一個樹形的多選框控制元件。
需求:
當選中頂層樹節點,子節點全部被選中,取消同上,當子節點被選中的時候,父節點顯示部分選中的狀態。
使用Qt設計器進行介面設計,然後通過訊號與槽進行連結,改變訊號(itemChanged(QTreeWidgetItem *item,int column)),實現這個訊號即可。
實現:
新建一個Widget自帶ui的專案,這個不多說了。
在設計器中將QTree Widget控制元件拖進widget。
在widget.h中新增如下標頭檔案以及程式碼:
```cpp
include
public: void init(); //初始化函式 void updateParentItem(QTreeWidgetItem item); public slots: void onTreeItemChanged(QTreeWidgetItem item,int column); ```
接下來在widget.cpp中實現上面的函式,並且在建構函式中呼叫:
建構函式新增如下程式碼:
cpp
init();
connect(ui->treeWidget,SIGNAL(itemChanged(QTreeWidgetItem*,int)),this,SLOT(onTreeItemChanged(QTreeWidgetItem*, int)));
init()實現
```cpp void myTreeWidget::init() { ui->treeWidget->clear(); QTreeWidgetItem group1 = new QTreeWidgetItem(ui->treeWidget); group1->setText(0,tr(二次)); group1->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable); group1->setCheckState(0,Qt::Unchecked); QTreeWidgetItem subItem11 = new QTreeWidgetItem(group1); subItem11->setCheckState(0,Qt::Unchecked); subItem11->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable); subItem11->setText(0,subItem11);
QTreeWidgetItem *subItem12 = new QTreeWidgetItem(group1);
subItem12->setCheckState(0,Qt::Unchecked);
subItem12->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem12->setText(0,subItem12);
QTreeWidgetItem *subItem13 = new QTreeWidgetItem(group1);
subItem13->setCheckState(0,Qt::Unchecked);
subItem13->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem13->setText(0,subItem13);
QTreeWidgetItem *subItem14 = new QTreeWidgetItem(group1);
subItem14->setCheckState(0,Qt::Unchecked);
subItem14->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem14->setText(0,subItem14);
QTreeWidgetItem *group2 = new QTreeWidgetItem(ui->treeWidget);
group2->setText(0,tr(三次));
group2->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
group2->setCheckState(0,Qt::Unchecked);
QTreeWidgetItem *subItem21 = new QTreeWidgetItem(group2);
subItem21->setCheckState(0,Qt::Unchecked);
subItem21->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem21->setText(0,subItem21);
QTreeWidgetItem *subItem22 = new QTreeWidgetItem(group2);
subItem22->setCheckState(0,Qt::Unchecked);
subItem22->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem22->setText(0,subItem22);
QTreeWidgetItem *subItem23 = new QTreeWidgetItem(group2);
subItem23->setCheckState(0,Qt::Unchecked);
subItem23->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem23->setText(0,subItem23);
QTreeWidgetItem *subItem24 = new QTreeWidgetItem(group2);
subItem24->setCheckState(0,Qt::Unchecked);
subItem24->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
subItem24->setText(0,subItem24);
} ```
onTreeItemChanged函式實現
cpp
void myTreeWidget::onTreeItemChanged(QTreeWidgetItem *item, int column)
{
QString itemText = item->text(0);
int count = item->childCount();
if(Qt::Checked == item->checkState(0))
{
if(count>0){
for(int i = 0; i < count; i++)
{
item->child(i)->setCheckState(0,Qt::Checked);
}
}
else
{
//是子節點
updateParentItem(item);
}
}
else if(Qt::Unchecked == item->checkState(0))
{
if(count>0){
for(int i = 0; i < count; i++)
{
item->child(i)->setCheckState(0,Qt::Unchecked);
}
}
else
{
//是子節點
updateParentItem(item);
}
}
}
updateParentItem函式實現
cpp
void myTreeWidget::updateParentItem(QTreeWidgetItem *item)
{
QTreeWidgetItem *parent = item->parent();
if(parent == NULL)
{
return;
}
int selectedCount = 0;
int childCount = parent->childCount();
for (int i = 0; i < childCount; i++)
{
QTreeWidgetItem *childItem = parent->child(i);
if(childItem->checkState(0) == Qt::Checked)
{
selectedCount++;
}
}
if(selectedCount <= 0)
{
//未選中狀態
parent->setCheckState(0,Qt::Unchecked);
}
else if(selectedCount > 0 && selectedCount < childCount)
{
parent->setCheckState(0,Qt::PartiallyChecked);
}
else if(selectedCount == childCount)
{
parent->setCheckState(0,Qt::Checked);
}
}
方便使用我們開啟設計器 右鍵TreeWidget控制元件選擇DoubleChicked,設定其雙擊改變狀態
```cpp
void myTreeWidget::on_treeWidget_itemDoubleClicked(QTreeWidgetItem item, int column) { QTreeWidgetItem parent = item->parent(); if(parent == NULL) { return; } if(Qt::Unchecked == item->checkState(0)) { item->setCheckState(0,Qt::Checked); } else if(Qt::Checked == item->checkState(0)) { item->setCheckState(0,Qt::Unchecked); } } ```
效果如下:
附上自此向上得控制元件示例合集,接下來準備詳細開始學習佈局。