在做QGIS方面的工作时,经常会用到在地图上绘制方面的需求,比如测量面积、测量长度、计算角度等等。
在绘制的时候,都会调用:paintEvent 这个函数
void MainCanvas::paintEvent(QPaintEvent *event) {
QgsMapCanvas::paintEvent(event);
//绘制内容
...
}
仔细想想,如果把所有的绘制工作都放到这个函数当中,可见是一个多么庞大的函数,就是拆分成小的函数候,也会造成这个类的臃肿。稍微做一下逻辑上的修改就有可能就会引起其他方面的问题,对以后的维护造成很大的困难。
所以要把所有的绘制工作拆分成不同的小的类便于维护和修改。提供统一的外观接口
绘制面积类:
class MeasureArea : public QObject {
Q_OBJECT
public:
MeasureArea();
MeasureArea(QObject *parent);
~MeasureArea();
//首先调用
void initCanvas(QgsMapCanvas* c);
void setDraw(bool b, QWidget* parent = nullptr);
void paintEvent();
void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
}
绘制长度类:
class TRUESYSDLL_EXPORT MeasureLine {
public:
MeasureLine();
~MeasureLine();
//首先调用
void initCanvas(QgsMapCanvas* c);
void setDraw(bool b, QWidget* parent = nullptr);
void paintEvent();
void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
}
绘制角度类:
class TRUESYSDLL_EXPORT MeasureAngle {
public:
MeasureAngle();
~MeasureAngle();
//首先调用
void initCanvas(QgsMapCanvas* c);
void setDraw(bool b);
void paintEvent();
void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
}
然后编写一个管理所有绘制相关的类:
class DrawManager {
private:
DrawManager();
static DrawManager* instance;
public:
~DrawManager();
static DrawManager* getInstance();
public:
void init(QgsMapCanvas* c);
void paintEvent(QPaintEvent *event);
void mouseDoubleClickEvent(QMouseEvent * event);
void mousePressEvent(QMouseEvent * event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent * event);
public:
void setMeasureLine(bool b);//设置测量线长度
void setMeasureArea(bool b);//设置测量面积
void setMeasureAngle(bool b);//设置测量角度
private:
void clearDraw();
private:
QgsMapCanvas* canvas;
MeasureLine* measureLine;//长度测量
MeasureArea* measureArea;//面积测量
MeasureAngle* measureAngle;//角度测量
};
看看这个类是如何管理所有绘制工作的
void DrawManager::init(QgsMapCanvas* c) {
canvas = c;
CoordinateManager::getInstance()->init(canvas);
measureLine->initCanvas(canvas);
measureArea->initCanvas(canvas);
measureAngle->initCanvas(canvas);
}
void DrawManager::paintEvent(QPaintEvent *event) {
measureLine->paintEvent();
measureArea->paintEvent();
measureAngle->paintEvent();
}
void DrawManager::mouseDoubleClickEvent(QMouseEvent * event) {
}
void DrawManager::mousePressEvent(QMouseEvent * event) {
measureLine->mousePressEvent(event);
measureArea->mousePressEvent(event);
measureAngle->mousePressEvent(event);
}
void DrawManager::mouseReleaseEvent(QMouseEvent *event) {
measureLine->mouseReleaseEvent(event);
measureArea->mouseReleaseEvent(event);
measureAngle->mouseReleaseEvent(event);
}
void DrawManager::mouseMoveEvent(QMouseEvent * event) {
measureLine->mouseMoveEvent(event);
measureArea->mouseMoveEvent(event);
measureAngle->mouseMoveEvent(event);
}
看到了吗?所有的绘制工作都在这个类中完成,包括和鼠标的操作。而且通关开关开控制当前地图上应该绘制那些那些内容:
void setMeasureLine(bool b);//设置测量线长度
void setMeasureArea(bool b);//设置测量面积
void setMeasureAngle(bool b);//设置测量角度
如何调用,这主绘制类中:
void MainCanvas::init() {
DrawManager::getInstance()->init(this);
}
void MainCanvas::paintEvent(QPaintEvent *event) {
QgsMapCanvas::paintEvent(event);
DrawManager::getInstance()->paintEvent(event);
}
void MainCanvas::mouseDoubleClickEvent(QMouseEvent * event) {
DrawManager::getInstance()->mouseDoubleClickEvent(event);
}
void MainCanvas::mousePressEvent(QMouseEvent * event) {
QgsMapCanvas::mousePressEvent(event);
DrawManager::getInstance()->mousePressEvent(event);
}
void MainCanvas::mouseReleaseEvent(QMouseEvent *event) {
QgsMapCanvas::mouseReleaseEvent(event);
DrawManager::getInstance()->mouseReleaseEvent(event);
}
void MainCanvas::mouseMoveEvent(QMouseEvent * event) {
QgsMapCanvas::mouseMoveEvent(event);
DrawManager::getInstance()->mouseMoveEvent(event);
}
只要是在主绘制界面调用绘制相应的接口就可以了。
这样设计的好处:客户端在调用的时候,不必考虑每个绘制的过程是如何实现的,只要知道调用那个函数就可以了,而且一旦被调用就可以实现所有的绘制过程,不必单独的调用每个绘制过程,是高内聚。
这样设计的目的:使真正绘制的对象远离实际绘制的对象,实现对象与对象之间的解耦。符合C++设计中的“开闭原则”。