QTreeView的使用总结1

来源:互联网 发布:windows to go可以 编辑:程序博客网 时间:2024/05/21 03:25

一、概述

Qt中 treeview的典型使用方法是model/view。这里不介绍model、view、delegate的工作方式。

model 、delegate与treeview的关联过程如下:

ui.treeView->setModel( pModel );ui.treeView->setItemDelegate( pDelegate );


二、设置TreeView的头部信息

1、设置表头

      方法一:void QStandardItemModel::setHorizontalHeaderLabels( const QStringList & labels );

              参数labels指定一个QStringList对象,该对象中的每个字符串对应一个列的名字。

      方法二:void QStandardItemModel::setHorizontalHeaderItem(int column, QStandardItem * item);

              参数 column指定列的索引,item指定列的内容

例子:分别使用上述两种方法设置TreeView头部信息

方法一:

QStringList ColumnStringList;ColumnStringList << QStringLiteral("车库") << QStringLiteral("信息");model->setHorizontalHeaderLabels( QStringList() << QStringLiteral("车库")<< QStringLiteral("信息") );QStandardItem* pColumnItem = model->horizontalHeaderItem(0);pColumnItem->setIcon( QIcon(":/TreeView_T/Resources/qt-logo.png") );pColumnItem->setToolTip(QStringLiteral("这是第一列") );pColumnItem = model->horizontalHeaderItem(1);pColumnItem->setIcon(QIcon(":/TreeView_T/Resources/qt-logo.png") );pColumnItem->setToolTip(QStringLiteral("这是第二列"));
方法二:

QStandardItem* pItem = new QStandardItem( QIcon(":/TreeView_T/Resources/qt-logo.png"), QStringLiteral("车库"));pItem->setToolTip( QStringLiteral("这是第一列"));QStandardItem* pItem1 = new QStandardItem( QIcon(":/TreeView_T/Resources/qt-logo.png"), QStringLiteral("信息") );pItem1->setToolTip( QStringLiteral("这是第二列"));model->setHorizontalHeaderItem( 0, pItem);model->setHorizontalHeaderItem( 1, pItem1);


2、隐藏表头

       通过QTreeView中的 header()->hide(),可以隐藏表头。


效果如下:

三、填充行与列

(1)、可以在行头部添加图标

例子:

QMap<QString, QIcon> m_IconMap;//存放公共图标QMap<QString, QIcon> m_CarportIconMap;  //车库公共图标//初始化图标库m_CarportIconMap[QStringLiteral("Port1")] = QIcon(QStringLiteral(":/cars1/Resources/cars1/3942000.ico"));m_CarportIconMap[QStringLiteral("Port2")] = QIcon(QStringLiteral(":/cars1/Resources/cars1/3942001.ico"));m_CarportIconMap[QStringLiteral("Port3")] = QIcon(QStringLiteral(":/cars1/Resources/cars1/3942002.ico"));m_CarportIconMap[QStringLiteral("Port4")] = QIcon(QStringLiteral(":/cars1/Resources/cars1/3942003.ico"));m_CarportIconMap[QStringLiteral("Port5")] = QIcon(QStringLiteral(":/cars1/Resources/cars1/3942004.ico"));m_IconMap[QStringLiteral("Audi")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/audi.ico") );m_IconMap[QStringLiteral("Bmw")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/bmw.ico") );m_IconMap[QStringLiteral("Buick")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/Buick.ico") );m_IconMap[QStringLiteral("Cadillac")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/cadillac.ico") );m_IconMap[QStringLiteral("Ferrari")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/ferrari.ico") );m_IconMap[QStringLiteral("Ford")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/ford.ico") );m_IconMap[QStringLiteral("Hyundai")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/hyundai.ico") );m_IconMap[QStringLiteral("Lexus")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/lexus.ico") );m_IconMap[QStringLiteral("Mazda")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/mazda.ico") );m_IconMap[QStringLiteral("Mercedesbenz")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/mercedesbenz.ico") );m_IconMap[QStringLiteral("Nissan")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/nissan.ico") );m_IconMap[QStringLiteral("Toyota")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/toyota.ico") );m_IconMap[QStringLiteral("Volkswagen")] = QIcon( QStringLiteral(":/cars_logo/Resources/cars_logo/Volkswagen.ico") );QStandardItem* pStandardItem = NULL;QStandardItem* pStandardChildItem = NULL;int i = 0;QMap<QString, QIcon>::const_iterator it1 = m_CarportIconMap.constBegin();for (QMap<QString, QIcon>::const_iterator it = m_IconMap.constBegin(); it != m_IconMap.constEnd(); ++it){if (i % 3 == 0){pStandardItem = new QStandardItem((it1 + (i / 3)).value(), (it1 + (i / 3)).key());model->appendRow(pStandardItem);}pStandardChildItem = new QStandardItem( it.value(), it.key());pStandardItem->appendRow( pStandardChildItem );pStandardItem->setChild( pStandardChildItem->row(),1, new QStandardItem( QString("this is %1").arg( it.key()) ));++i;}
效果如下:


(2)、可以在行头添加单选框
使用QStandardItem时与checkbox相关的几个函数:

       void QStandardItem::setCheckable(bool checkable);     //设置Item是否有复选框功能

       void QStandardItem::setCheckState(Qt::CheckState state);    //设置Item的复选状态

       Qt::CheckState有三种状态:Qt::Unchecked :未选中状态、Qt::PartiallyChecked:部分选中状态(层次模型中的子项有一部分处于选中状态)、Qt::Checked:选中状态

       void QStandardItem::setTristate(bool tristate);    //设置Item是否是三态的(Qt::Unchecked、Qt::PartiallyChecked、Qt::Checked)

       Qt::CheckState QStandardItem::checkState() const ;    //返回Item的复选状态

       bool QStandardItem::isCheckable() const ;     //判断Item是否是可复选的

       bool QStandardItem::isTristate() const ;     //判断Item是否是三态的

例子:

QStandardItem* pStandardItem = NULL;QStandardItem* pStandardChildItem = NULL;int i = 0;QMap<QString, QIcon>::const_iterator it1 = m_CarportIconMap.constBegin();for (QMap<QString, QIcon>::const_iterator it = m_IconMap.constBegin(); it != m_IconMap.constEnd(); ++it){if (i % 3 == 0){pStandardItem = new QStandardItem((it1 + (i / 3)).value(), (it1 + (i / 3)).key());//设置Item为三态pStandardItem->setTristate( true );//设置Item为部分选中状态pStandardItem->setCheckState( Qt::PartiallyChecked );model->appendRow(pStandardItem);}pStandardChildItem = new QStandardItem( it.value(), it.key());//设置Item具有单选能力pStandardChildItem->setCheckable( true );//设置Item不具有三态pStandardChildItem->setTristate( false );//设置Item为选中状态pStandardChildItem->setCheckState( /*Qt::PartiallyChecked*/  Qt::Checked );pStandardItem->appendRow( pStandardChildItem );pStandardItem->setChild( pStandardChildItem->row(),1, new QStandardItem( QString("this is %1").arg( it.key()) ));++i;}
效果如下:



(3)三态复选框的智能关联(如果子项全选,父级也需要全选,如果子项部分选,父级就不完全选)

/*QTreeView在QStandardItemModel设置复选框后,并不是按照规则的,需要通过代码设置三态复选框主要体现在树形控件里,如果子项目全选,父级需要全选,如果子项目部分选择,父级就是不完全选*//*item checkbox单击响应函数*/void MyDelegate::treeItem_CheckChanged(QStandardItem* item){if (item == nullptr){return;}if (item->isCheckable() ){//如果item是存在复选框的,那么就进行下面的操作Qt::CheckState state = item->checkState(); //获取当前的选择状态if (item->isTristate()){//如果item是三态的,说明可以对子目录进行全选和全不选的设置if (state != Qt::PartiallyChecked){//当前是选中状态,需要对其子项目设置为全选treeItem_CheckAllChild(item, state == Qt::Checked ? true : false);}}else{//说明是两态的,两态会对父级的三态有影响//判断兄弟节点的情况treeItem_CheckChildChanged( item );}}} //// \brief 递归设置所有的子项目为全选或全不选状态// \param item 当前项目// \param check true时为全选,false时全不选//void MyDelegate::treeItem_CheckAllChild(QStandardItem* item, bool check){if (item == nullptr){return;}int rowCount = item->rowCount();for (int i = 0; i < rowCount; ++i ){QStandardItem* childItems = item->child( i );treeItem_checkAllChild_recursion( childItems, check);}if (item->isCheckable()){item->setCheckState( check ? Qt::Checked : Qt::Unchecked);}}void MyDelegate::treeItem_checkAllChild_recursion(QStandardItem* item, bool check){if (item == nullptr){return;}int rowCount = item->rowCount();for (int i = 0; i < rowCount; ++i){QStandardItem* childItems = item->child( i );treeItem_checkAllChild_recursion( childItems, check);}if (item->isCheckable()){item->setCheckState( check ? Qt::Checked : Qt::Unchecked );}}//// \brief 根据子节点的改变,更改父节点的选择情况// \param item////此函数也是一个递归函数,首先要判断的是父级是否到达顶层//,到达底层作为递归的结束,然后通过函数checkSibling判断当前的兄弟节点的具体情况//void MyDelegate::treeItem_CheckChildChanged(QStandardItem* item){if (nullptr == item){return;}Qt::CheckState siblingState = checkSibling( item );QStandardItem* parentItem = item->parent();if (nullptr == parentItem){return;}if (Qt::PartiallyChecked == siblingState){if (parentItem->isCheckable() && parentItem->isTristate())parentItem->setCheckState( Qt::PartiallyChecked );}else if (Qt::Checked == siblingState){if (parentItem->isCheckable())parentItem->setCheckState( Qt::Checked);}else{if (parentItem->isCheckable())parentItem->setCheckState( Qt::Unchecked );}treeItem_CheckChildChanged( parentItem );}//// \brief 测量兄弟节点的情况,如果都选中返回Qt::Checked,都不选中Qt::Unchecked, // \不完全选中返回Qt::PartiallyChecked// \param item// \return Qt::CheckState MyDelegate::checkSibling(QStandardItem* item){//先通过父节点获取兄弟节点QStandardItem* parent = item->parent();if (nullptr == parent){return item->checkState();}int brotherCount = parent->rowCount();int checkedCount(0), unCheckedCount( 0 );Qt::CheckState state;for (int i = 0; i < brotherCount; ++i){QStandardItem* siblingItem = parent->child( i );state = siblingItem->checkState();if (Qt::PartiallyChecked == state){return Qt::PartiallyChecked;}else if (Qt::Unchecked == state){++unCheckedCount;}else{++checkedCount;}if (checkedCount > 0 && unCheckedCount > 0){return Qt::PartiallyChecked;}}if (unCheckedCount > 0){return Qt::Unchecked;}return Qt::Checked;}

四、QStandardItemModel的角色控制

<一>、自定义角色的使用

        在MFC中,树形控件CTreeCtrl是通过SetItemData函数来对节点设置一个指针的值,这个值可以是个指针、DWORD值、自定义的标志或者自定义类型的指针。Qt的TreeView比MFC的CTreeCtrl封装的更好,其功能也更强大,以至于可以给每个节点设定非常非常多的值(只要内存足够)。QTreeView只负责显示渲染,数据都有Model来负责管理。我们可以使用setData函数来为节点设置数据。

        setData函数在Model和Item中都有,功能都一样。QStandardItemModel中setData函数的定义:

        virtual bool setData( const QModelIndex & index,   const  QVarient & value,  int role = Qt::EditRole);

QStandardItem中setData的定义是:

        virtual void setData( const QVaritant & value,  int role = Qt::UserRole + 1 );

         参数:value:是要设置的值, role是一个int型数据,Qt中把这个称为role角色,实际就是对设定值的标定,因为item可以设置许多值,这就需要一个用以区分的标志,这个区分标志就叫角色。Qt已经把经常用到的角色内容定义好了,我们可以自定义角色标志,但不要和定义好的那些标志冲突,否则会不起作用。如果显示文字就用Qt::DisplayRole,要告诉QTreeView需要改变背景颜色,就标定Qt::BackgroundRole,要改变字体就标定Qt::FontRole等等。从中可以看出,role就是一个标示,用来标定存放在item李淼的值集体用于什么功能,系统默认的role参看Qt::ItemDataRole枚举。自定义的Role,就从Qt::UserRole开始往上加。

例子:

        定义用户自定义的role:

#define ROLE_MARK_TYPE Qt::UserRole + 100#define MARK_FOLDER 1#define MARK_ITEM   2
       为Item设置数据

QStandardItem* pStandardItem = NULL;QStandardItem* pStandardChildItem = NULL;int i = 0;QMap<QString, QIcon>::const_iterator it1 = m_CarportIconMap.constBegin();for (QMap<QString, QIcon>::const_iterator it = m_IconMap.constBegin(); it != m_IconMap.constEnd(); ++it){if (i % 3 == 0){pStandardItem = new QStandardItem((it1 + (i / 3)).value(), (it1 + (i / 3)).key());pStandardItem->setCheckable( true );//设置Item为三态pStandardItem->setTristate( true );//为Item设置自定义rolepStandardItem->setData( MARK_FOLDER, ROLE_MARK_TYPE );  //标记该item为文件夹model->appendRow(pStandardItem);}pStandardChildItem = new QStandardItem( it.value(), it.key());//设置Item具有单选能力pStandardChildItem->setCheckable( true );//设置Item不具有三态pStandardChildItem->setTristate( false );//为Item设置自定义rolepStandardChildItem->setData( MARK_ITEM, ROLE_MARK_TYPE ); //标记该Item为具体的项pStandardItem->appendRow( pStandardChildItem );pStandardItem->setChild( pStandardChildItem->row(),1, new QStandardItem( QString("this is %1").arg( it.key()) ));++i;}
        在鼠标左键点击TreeView中的Item时,通过对话框显示当前点击的Item的类型:是文件夹还是具体的项?

bool MyDelegate::editorEvent(QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index){QStandardItemModel* pModel = static_cast<QStandardItemModel*>( model );if (event->type() == QEvent::MouseButtonPress){if (static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton){if (model->data(index, ROLE_MARK_TYPE) == MARK_FOLDER){QMessageBox::information(NULL, "TypeInfo", "this is folder!", QMessageBox::Ok);}else if (model->data(index, ROLE_MARK_TYPE) == MARK_ITEM ){QMessageBox::information(NULL, "TypeInfo", "this is item!", QMessageBox::Ok);}}}return QStyledItemDelegate::editorEvent( event, model, option, index );}

<二>、系统角色的使用
        Qt定义好的角色如下:

例子:

bool MyDelegate::editorEvent(QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index){QStandardItemModel* pModel = static_cast<QStandardItemModel*>( model );if (event->type() == QEvent::MouseButtonPress){if (static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton){if (model->data(index, ROLE_MARK_TYPE) == MARK_FOLDER){QMessageBox::information(NULL, "TypeInfo", "this is folder!", QMessageBox::Ok);}else if (model->data(index, ROLE_MARK_TYPE) == MARK_ITEM ){QMessageBox::information(NULL, "TypeInfo", "this is item!", QMessageBox::Ok);}//设置Item的图标覆盖为某一颜色pModel->itemFromIndex(index)->setData( QColor(0, 255, 0, 200), Qt::DecorationRole);//设置气泡提示信息pModel->itemFromIndex(index)->setData(QString("Tip:%1").arg(pModel->itemFromIndex(index)->text() ), Qt::ToolTipRole);//设置背景色pModel->itemFromIndex(index)->setData(QColor(232, 209, 57, 200), Qt::BackgroundRole);}}return QStyledItemDelegate::editorEvent( event, model, option, index );}
效果:



参看:http://www.tuicool.com/articles/FvaYNn

参看:http://www.it165.net/pro/html/201405/14029.html

0 0
原创粉丝点击