在上一篇文章中,实现了图层列表。本篇文章,我们讲解如何在图层列表上,点击图层右键出现菜单项,并添加相应的功能。计划实现如下几点功能:
1.添加图层组、展开/折叠图层组;
2.图层目录右键菜单项;
3.zoom to layer、删除图层图层组、重命名图层图层组、显示要素个数。
接着上一篇文章,更新了初始化图层列表函数的内容,整体代码如下,接下来会依次讲解里面的内容。
//新建图层树形控件
mLayerTreeView = new QgsLayerTreeView(this);
mLayerTreeView->setObjectName(QStringLiteral("theLayerTreeView"));
//创建QgsLayerTreeModel 实例,并允许用户通过点选复选框手动隐藏/显示图层
QgsLayerTreeModel* model = new QgsLayerTreeModel(QgsProject::instance()->layerTreeRoot(), this);
model->setFlag(QgsLayerTreeModel::AllowNodeChangeVisibility);
model->setFlag(QgsLayerTreeModel::AllowNodeReorder);
model->setFlag(QgsLayerTreeModel::AllowNodeRename);
model->setFlag(QgsLayerTreeModel::ShowLegendAsTree);
model->setFlag(QgsLayerTreeModel::UseEmbeddedWidgets);
model->setFlag(QgsLayerTreeModel::UseTextFormatting);
model->setAutoCollapseLegendNodes(10);
//将View视图与Model数据绑定
mLayerTreeView->setModel(model);
//将工程实例中的图层根节点与画布绑定,实现与地图画布控件的数据交互
mLayerTreeCanvasBridge = new QgsLayerTreeMapCanvasBridge(QgsProject::instance()->layerTreeRoot(), mMapCanvas, this);
//添加图层组
QAction* addGroup = new QAction(tr("Add Group"), this);
addGroup->setIcon(createIcon(Add_Group));
addGroup->setToolTip(tr("Add Group"));
connect(addGroup, &QAction::triggered, mLayerTreeView->defaultActions(), &QgsLayerTreeViewDefaultActions::addGroup);
//展开所有图层组
QAction* actionExpandAll = new QAction(tr("Expand All"), this);
actionExpandAll->setIcon(createIcon(Expand_All));
actionExpandAll->setToolTip(tr("Expand All"));
connect(actionExpandAll, &QAction::triggered, mLayerTreeView, &QgsLayerTreeView::expandAllNodes);
//折叠所有图层组
QAction* actionCollapseAll = new QAction(tr("Collapse All"), this);
actionCollapseAll->setIcon(createIcon(Collapse_All));
actionCollapseAll->setToolTip(tr("Collapse All"));
connect(actionCollapseAll, &QAction::triggered, mLayerTreeView, &QgsLayerTreeView::collapseAllNodes);
QToolBar* toolbar = new QToolBar(this);
toolbar->setIconSize(QSize(16, 16));
toolbar->addAction(addGroup);
toolbar->addAction(actionExpandAll);
toolbar->addAction(actionCollapseAll);
QVBoxLayout* vboxLayout = new QVBoxLayout;
vboxLayout->setContentsMargins(0, 0, 0, 0);
vboxLayout->setSpacing(0);
vboxLayout->addWidget(toolbar);
vboxLayout->addWidget(mLayerTreeView);
QWidget* w = new QWidget;
w->setLayout(vboxLayout);
//设置点击右键出现菜单项
mLayerTreeView->setMenuProvider(new QtGisLayerTreeViewMenuProvider(mLayerTreeView, mMapCanvas));
//将View添加到左侧的Dock控件中展示
mLayerMapDock->setWidget(w);
一、添加图层组、展开/折叠图层组
1.首先新建添加图层组、展开/折叠图层组三个QAction。
分别将这三个QAction的点击动作与槽函数绑定。
在mLayerTreeView->defaultActions()所有默认action中,实现了addGroup方法,所以这里的receiver是mLayerTreeView->defaultActions()。
connect(addGroup, &QAction::triggered, mLayerTreeView->defaultActions(), &QgsLayerTreeViewDefaultActions::addGroup);
而展开/折叠的图层组是由QgsLayerTreeView实现的,所以这里的receiver是mLayerTreeView。
connect(actionExpandAll, &QAction::triggered, mLayerTreeView, &QgsLayerTreeView::expandAllNodes);
connect(actionCollapseAll, &QAction::triggered, mLayerTreeView, &QgsLayerTreeView::collapseAllNodes);
2.将QAction添加到QToolBar中,并将QToolBar与图层树控件mLayerTreeView一起添加到左侧Dock控件中。
二、图层目录右键菜单项
为图层目录添加右键菜单项,是由以下这句话实现:
//设置点击右键出现菜单项
mLayerTreeView->setMenuProvider(new QtGisLayerTreeViewMenuProvider(mLayerTreeView, mMapCanvas));
我们可以看QGIS源码中对于setMenuProvider函数的定义,说明函数里面参数是一个QgsLayerTreeViewMenuProvider 类的实例。
//! Sets provider for context menu. Takes ownership of the instance
void setMenuProvider( QgsLayerTreeViewMenuProvider *menuProvider SIP_TRANSFER );
再看QgsLayerTreeViewMenuProvider类的定义,其中createContextMenu函数就是创建菜单项的函数,我们只需要在自定义的函数中继承QgsLayerTreeViewMenuProvider类,并实现createContextMenu函数即可。
class GUI_EXPORT QgsLayerTreeViewMenuProvider
{
public:
virtual ~QgsLayerTreeViewMenuProvider() = default;
//! Returns a newly created menu instance (or NULLPTR on error)
virtual QMenu *createContextMenu() = 0 SIP_FACTORY;
};
1.添加自定义类
自定义类的头文件实现如下,其中mMapCanvas和mView用于存储从主类传过来的地图画布和图层列表。
#include "qgslayertreeview.h"
class QgsMapCanvas;
class QtGisLayerTreeViewMenuProvider :
public QgsLayerTreeViewMenuProvider
{
public:
QtGisLayerTreeViewMenuProvider(QgsLayerTreeView* layerTreeView, QgsMapCanvas* mapCanvas);
~QtGisLayerTreeViewMenuProvider();
virtual QMenu* createContextMenu() override;
private:
QgsMapCanvas* mMapCanvas;
QgsLayerTreeView* mView;
};
在.cpp文件的构造函数中,给mMapCanvas和mView赋值。
QtGisLayerTreeViewMenuProvider::QtGisLayerTreeViewMenuProvider(QgsLayerTreeView* layerTreeView, QgsMapCanvas* mapCanvas)
:QgsLayerTreeViewMenuProvider()
, mMapCanvas(mapCanvas)
, mView(layerTreeView)
{
}
2.实现createContextMenu函数,添加菜单项。
createContextMenu函数的整体代码如下:
QMenu* QtGisLayerTreeViewMenuProvider::createContextMenu()
{
QMenu* menu = new QMenu;
QModelIndex index = mView->currentIndex();
if (!index.isValid()) return nullptr;
QgsLayerTreeNode* node = mView->index2node(index);
if (QgsLayerTree::isGroup(node)) {
menu->addAction(mView->defaultActions()->actionRemoveGroupOrLayer(menu));
menu->addAction(mView->defaultActions()->actionRenameGroupOrLayer(menu));
}
else if(QgsLayerTree::isLayer(node)){
QgsMapLayer* layer = QgsLayerTree::toLayer(node)->layer();
if (layer) {
menu->addAction(mView->defaultActions()->actionZoomToLayer(mMapCanvas,menu));
menu->addAction(mView->defaultActions()->actionRemoveGroupOrLayer(menu));
menu->addAction(mView->defaultActions()->actionRenameGroupOrLayer(menu));
}
QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>(layer);
if (vLayer) {
menu->addAction(mView->defaultActions()->actionShowFeatureCount(menu));
}
}
return menu;
}
接下来依次讲解createContextMenu函数中的内容。
首先获取图层列表中的当前图层节点。
QModelIndex index = mView->currentIndex();
if (!index.isValid()) return nullptr;
QgsLayerTreeNode* node = mView->index2node(index);
如果该节点是图层组,则向菜单menu中添加删除/重命名图层组的功能
if (QgsLayerTree::isGroup(node)) {
menu->addAction(mView->defaultActions()->actionRemoveGroupOrLayer(menu));
menu->addAction(mView->defaultActions()->actionRenameGroupOrLayer(menu));
}
如果是图层,且是矢量图层则添加显示要素个数的功能。
QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>(layer);
if (vLayer) {
menu->addAction(mView->defaultActions()->actionShowFeatureCount(menu));
}
3.其他功能实现
如果还想实现其他功能,可以参考QgsLayerTreeViewDefaultActions这个类中,提供的功能,按照上面的方式提供即可;如果需要实现一些自定义的功能,则自己定义QAction,添加到menu中并实现相应的功能即可。
最后实现的效果如下:
项目git地址:https://github.com/guoqiongGit/QtGisDemo
欢迎下载共同交流、学习。