用qt写一个绘图小例子演示c++中面向对象及抽象的好处

我对代码中抽象对象好处的理解是:提高代码的复用性。
假设我们有这样的需求,要在界面上按下鼠标,拖动之后松开鼠标,然后就在界面上绘制出了线、矩形,如下图c所示:
在这里插入图片描述
那么我们首先贴上第一种方法的代码:
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPainter>
#include <QMouseEvent>
namespace Ui {
class MainWindow;
}
class myLine//定义一个线类,里面用两个字段表示线的起点和终点
{
public:
    QPoint start;
    QPoint end;
    myLine()
    {

    }
    myLine(const QPoint& start,const QPoint& end)
    {
        this->start = start;
        this->end = end;
    }
};
class myRect//定义一个矩形类,里面定义3个字段,表示矩形起点、宽度、高度
{
public:
    QPoint start;
    int nWidth;
    int nHeight;
    myRect()
    {

    }
    myRect(const QPoint& start,const int& nWidth,const int& nHeight)
    {
        this->start = start;
        this->nWidth = nWidth;
        this->nHeight = nHeight;
    }
};
//1.add class myCircle
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseReleaseEvent(QMouseEvent *event);
    virtual void paintEvent(QPaintEvent *event);
    QVector<myLine> vmyLine;
    myLine          mylineCrt;
    QVector<myRect> vmyRect;
    myRect          myrectCrt;
    //2.add QVector<myCircle> vmyCircle;
    //3.add myCircle          mycircleCrt;
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    mylineCrt.start = event->pos();
    myrectCrt.start = event->pos();
    //4.add mycircleCtr.centerpoint = event->pos();
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    mylineCrt.end = event->pos();
    myrectCrt.nWidth = qAbs(event->x()-myrectCrt.start.x());
    myrectCrt.nHeight = qAbs(event->y()-myrectCrt.start.y());
    vmyLine.append(mylineCrt);
    vmyRect.append(myrectCrt);
    //5.add vmyCircle.append(mycircleCrt);
    this->repaint();
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    //绘制一个从
    QPen pen(QColor(0,0,255));
    pen.setWidth(5);
    QPainter g(this);
    g.setPen(pen);
    //画直线
    for(int i = 0;i<vmyLine.count();i++)
    {
        g.drawLine(vmyLine[i].start,vmyLine[i].end);
    }
    //画矩形
    for(int i = 0;i<vmyRect.count();i++)
    {
        g.drawRect(vmyRect[i].start.x(),vmyRect[i].start.y(),vmyRect[i].nWidth,vmyRect[i].nHeight);
    }
    //6.add 画圆形
}

好,这是第一种方法,也是很多新手常用的方法。
现在设想一下,如果客户的需求变了,需要我们添加绘制一个圆形,那么我们需要添加的代码包括上面标注出来的6个地方(这也是为什么我们这些程序猿天天加班的原因~)
然后我们来看第二种,即抽象之后的代码
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPainter>
#include <QMouseEvent>
#include <QtMath>
namespace Ui {
class MainWindow;
}
class myShape
{
public: myShape()
    {

    }
    virtual ~myShape()//因为类里面有drawShape纯虚函数,所以要有虚析构函数
    {

    }
    virtual void drawShape(QPen *pen,QPainter *g) = NULL;
};

class myLine:public myShape//定义一个线类,里面用两个字段表示线的起点和终点
{
public:
    QPoint start;
    QPoint end;
    myLine()
    {

    }
    myLine(const QPoint& start,const QPoint& end)
    {
        this->start = start;
        this->end = end;
    }
    virtual void drawShape(QPen *pen,QPainter *g)
    {
        g->setPen(*pen);
        g->drawLine(start,end);
    }
};
class myRect:public myShape//定义一个矩形类,里面定义3个字段,表示矩形起点、宽度、高度
{
public:
    QPoint start;
    int nWidth;
    int nHeight;
    myRect()
    {

    }
    myRect(const QPoint& start,const int& nWidth,const int& nHeight)
    {
        this->start = start;
        this->nWidth = nWidth;
        this->nHeight = nHeight;
    }
    virtual void drawShape(QPen *pen,QPainter *g)
    {
        g->setPen(*pen);
        g->drawRect(start.x(),start.y(),nWidth,nHeight);
    }
};
//1.add class myCircle
class myCircle:public myShape//定义一个矩形类,里面定义3个字段,表示矩形起点、宽度、高度
{
public:
    QPoint centerpoint;
    qreal nRadius;
    myCircle()
    {

    }
    myCircle(const QPoint& start,const qreal& nRadius)
    {
        this->centerpoint = start;
        this->nRadius = nRadius;
    }
    virtual void drawShape(QPen *pen,QPainter *g)
    {
        g->setPen(*pen);
        g->drawEllipse((int)centerpoint.x()-nRadius,(int)centerpoint.y()-nRadius,(int)nRadius*2,(int)nRadius*2);
    }
};
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseReleaseEvent(QMouseEvent *event);
    virtual void paintEvent(QPaintEvent *event);
    QPoint m_StartPoint;
    QVector<myShape*> vMyShape;
    //QVector<myLine> vmyLine;
    //QVector<myRect> vmyRect;
    //QVector<myCircle> vmyCircle;
private:
    Ui::MainWindow *ui;
};

mainwindow.cpp

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    m_StartPoint = event->pos();
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    vMyShape.append(new myLine(m_StartPoint,event->pos()));
    vMyShape.append(new myRect(m_StartPoint,event->x()-m_StartPoint.x(),event->y()-m_StartPoint.y()));
    //2.add
    qreal nRadius = qSqrt(qAbs(event->x()-m_StartPoint.x())*qAbs(event->x()-m_StartPoint.x())+qAbs(event->y()-m_StartPoint.y())*qAbs(event->y()-m_StartPoint.y()));
    vMyShape.append(new myCircle(m_StartPoint,nRadius));
    this->repaint();
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    //绘制一个从
    QPen pen(QColor(0,0,255));
    pen.setWidth(5);
    QPainter g(this);
    g.setPen(pen);
//    //画直线
//    for(int i = 0;i<vmyLine.count();i++)
//    {
//        g.drawLine(vmyLine[i].start,vmyLine[i].end);
//    }
//    //画矩形
//    for(int i = 0;i<vmyRect.count();i++)
//    {
//        g.drawRect(vmyRect[i].start.x(),vmyRect[i].start.y(),vmyRect[i].nWidth,vmyRect[i].nHeight);
//    }
    //画图形
    for(int i = 0;i<vMyShape.size();i++)
    {
        vMyShape[i]->drawShape(&pen,&g);
    }
}

可以看到,第二种方法用了抽象的概念,将三种图形抽象成了一个myShape,在代码中的体现就是定义了一个基类myShape类,其他所有的图像类都继承自这个基类,然后在每个子类中都添加了drawShape()方法,这样在界面的paintEvent(QPaintEvent *event)方法中绘图的时候就不需要分各种图形来单独绘制了。可以看到,用第二种方法在用户添加绘制圆形的需求的时候,需要添加更改代码的地方减少到了2处。极大提高了代码的复用性!
最后贴上一张运行结果图:
在这里插入图片描述
源码地址
https://download.csdn.net/download/weixin_43935474/12235320

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GreenHandBruce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值