QGIS二次开发02:交互动作实现

地图交互动作就是通过鼠标操作与地图间的互动。动作包括按下(press)、按键弹起(release)、鼠标移动(move)、双击等等。

QGIS实现地图的交互主要是通过继承QgsMapTool这个类实现,目前集成了QgsMapToolZoom(拉框缩放)、QgsMapToolPan(地图移动)、QgsMapToolEmitPoint(点击地图)、QgsMapToolExtent(拉框)、QgsMapToolEdit(交互编辑)、QgsMapToolIdentify(点击矢量要素)。

这些个性动作主要是实现了QgsMapTool的几个接口:

virtual void  canvasDoubleClickEvent (QgsMapMouseEvent *e)
双击鼠标
virtual void  canvasMoveEvent (QgsMapMouseEvent *e)
鼠标移动
virtual void  canvasPressEvent (QgsMapMouseEvent *e)
鼠标按下
virtual void  canvasReleaseEvent (QgsMapMouseEvent *e)
鼠标抬起

下面我们将通过一个封装类实现点击画点的交互动作

一、思路

动作逻辑:点击地图->获取点击处的坐标->绘制地图

实现:继承QgsMapToolEmitPint,实现canvasReleaseEvent即可,如下:

void SHQgsMapToolEmitPoint::canvasReleaseEvent(QgsMapMouseEvent *e){    
    QgsMapToolEmitPoint::canvasReleaseEvent(e);
    if(!mMapCanvas)return;
    QgsRubberBand *rb = new QgsRubberBand(mMapCanvas,QgsWkbTypes::PointGeometry);
    rb->setSize(100);
    rb->setColor(QColor(255,0,0));
    rb->addPoint(e->mapPoint);    //画点
}

二、进阶

如果我们现在有个新的需求,比如实现点击获取坐标,显然我们依照上面的思路通过再继承QgsMapToolEmitPoint也可以实现。但很明显“点击画点”和“点击获取坐标"的实现基本都差不多,区别仅仅在于最后一步的实现不同而已。能否再抽象,实现更佳的封装和调用呢。答案是明显了,思路:

1、定义不同的交互动作

2、设置动作

3、点击时发送信号传送坐标

4、在槽函数中根据动作不同对坐标进行不同处理,从而实现点击获取坐标和点击绘制

如下:

第一步:定义动作

enum MapAction{
        Null,               //无动作
        PointClick,         //点击
        DrawPoint,          //绘制点
    };
    Q_ENUM(MapAction);

第二步:setAction定义和实现,信号和槽函数关联

//mAction用来记录当前动作的成员变量

void MyTest::setAction(MapAction action){
    if(action==MapAction::PointClick || action==MapAction::DrawPoint){
        mAction = action;
        if(!this->mEmitPointTool){
            this->mEmitPointTool = new MyQgsMapToolEmitPoint(this->m_mapCanvas);    connect(mEmitPointTool,SIGNAL(signal_point_click(QgsPointXY)),this,SLOT(handlePointClickEvent(QgsPointXY)));
        }
        this->m_mapCanvas->setMapTool(this->mEmitPointTool);
    }else{
        mAction = MapAction::Null;
        QgsMapTool *tool = this->m_mapCanvas->mapTool();
        this->m_mapCanvas->unsetMapTool(tool);
    }

}

实现点击类,增加坐标的返回

//重载canvasReleaseEvent,实现信号signal_point_click的发送,传递回点击处坐标

void MyMapToolEmitPoint::canvasReleaseEvent(QgsMapMouseEvent *e){    
    QgsMapToolEmitPoint::canvasReleaseEvent(e);
    if(!mMapCanvas)return;
    emit signal_point_click(e->mapPoint);
}

第三步:实例化MyMapToolEmitPoint,并作为成员变量

//m_mapCanvas是地图画布指针
MyQgsMapToolEmitPoint mEmitPointTool = new MyQgsMapToolEmitPoint(this->m_mapCanvas);

第四步:槽函数实现

/**
 * 处理点击事件
 * @brief SHQgisMap2DHandler::handlePointClickEvent
 * @param xy
 */
void SHQgisMap2DHandler::handlePointClickEvent(QgsPointXY xy){

    if(m_action==SHMapAction::MapAction::PointClick)    {
        QString msg = QString("%1").arg(xy.x());
        msg += QString(",%1").arg(xy.y());
        QDebug<setSize(100);
        rb->setColor(QColor(200,0,0));
        rb->addPoint(xy);        
    }

}

第五步:调用

setAction(MapAction::DrawPoint);

设置点击画点动作,在地图上点击即可以绘制点对象。

三、再进阶

实现交互动作后的回调,如setAction(xxx,myCallBack);

思路:1、定义一个回调类,比如MyCallBack,里面有不同的实现的回调函数callback

           2、在上面的槽函数里调用具体的回调函数callback即可

当然用信号和槽函数也可以实现类似。

你可能感兴趣的:(QGIS,c++,qt,交互)