Qt 项目视图组(Item Views)与项目控件组(Item Widget)

项目视图组(Item Views)

项目视图组如图所示

项目视图组各个控件名称解释:

  • List View :清单视图
  • Tree View :树视图
  • Table View :表视图
  • Column View :列视图
  • Undo View :撤销列表

首先介绍一下Table View 和 Table Widget的区别

区别如下表

区别



QTableViewQTableWidget
继承关系QTableWidget继承自QTableView
使用数据模型setModel可以使用setModel设置数据模型setModel是私有函数,不能使用该函数设置数据模型
显示复选框没有函数实现复选框QTableWidgetItem类中的setCheckState (Qt::Checked); 可以设置复选框
与QSqlTableModel绑定QTableView能与QSqlTableModel绑定QTableWidget不能与QSqlTableModel绑定
  • 模型:所有的模型都基于QAbstractItemModel类,该类为抽象基类。
  • 视图:所有的视图都是从QAbstractItemView继承。

Item Views和Item Widgets的关系和区别

这两类控件都可以实现界面的表项视图展示,二者之间存在关系和区别:
1、Item Views(Model-Based)类内的控件是Item Widgets(Item-Based)内对应控件的父类,如QTreeWidget是从QTreeView派生的;

2、Item Views(Model-Based)的对象进行数据操作相对比较复杂,但处理及展示大数据量时性能高,而Item Widgets的数据操作比较简单,但处理及展示大数据量时性能相对低;

3、Item Views类控件是MVC(Model、View、Controller)架构的一种简化,数据和展现及实现逻辑分开,数据在Model中存储和操作,View负责展现、界面操作及逻辑控制;Item Widgets则将数据、展现及控制合并在一起,开发中没有Item Views灵活,实际上Item Widgets就是在Item Views的基础上绑定了一个默认的存储并提供了相关方法。

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绑定。比如下面这段代码

    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创建,否则视图不能随着模型得改变而改变。

典型错误:

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)));
    }
}

正确的写法应该是这样的:

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中添加如下头文件以及代码:

#include<QTreeWidgetItem>

public:
void init(); //初始化函数 void updateParentItem(QTreeWidgetItem *item);
public slots:
void onTreeItemChanged(QTreeWidgetItem *item,int column);

接下来在widget.cpp中实现上面的函数,并且在构造函数中调用:

构造函数添加如下代码:

init();
connect(ui->treeWidget,SIGNAL(itemChanged(QTreeWidgetItem,int)),this,SLOT(onTreeItemChanged(QTreeWidgetItem, int)));

init()实现

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函数实现

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 &lt; 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 &lt; count; i++) 
                item->child(i)->setCheckState(0,Qt::Unchecked);

        }
        else    //是子节点
            updateParentItem(item);

    }
}

updateParentItem函数实现

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,设置其双击改变状态

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);

}

效果如下:


已发布

分类

来自

标签:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理