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); } } ```
效果如下:
附上自此向上得控件示例合集,接下来准备详细开始学习布局。