【C++ 2.1】、基于QPainter实现多继承图形绘制

本文介绍如何在Qt环境中利用多态特性进行图形绘制,包括不同形状类的设计与实现,以及通过ShapeManager统一管理并绘制这些图形。文章还探讨了解决因图形对象生命周期问题导致的程序崩溃的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、绘制原理

	建立一个Qt Widgets Application 工程
	main.cpp 不需添加内容
	在mainwindow.h文件添加 void paintEvent(QPaintEvent *event)
	在mainwindow.cpp文件重写 void paintEvent(QPaintEvent *event)

	重新paintEvent(QPaintEvent *event)时,
	会实例化一个Qpainter,每个图形的类内Draw()都会调用Qpainter的对应的画图函数,如drawLine(),drawRect(). 

重写 void paintEvent(QPaintEvent *event) 如下:

void MainWindow::paintEvent(QPaintEvent *event){

    QPainter painter(this);

    QPen pen;
    pen.setColor(Qt::black);           // 设置画笔为黑色
    pen.setWidth(3);				//设置画笔粗细,太细了,再加上坐标取得太小,绘制出来了,但是看不到,让我崩溃半天
    painter.setPen(pen);                // 设置画笔


    CPoint point1(200,0);
    CPoint point2(100,100);
    CPoint point3(300,100);

    //绘制一个三角形
    CTriangle ctri(point1,point2,point3);
   // ctri.Draw(painter);

    //绘制一个圆1
    CCircle cir(point2,50);
    //cir.Draw(painter);

    //绘制一个圆2
    CPoint point4(250,100);
    CCircle cir1(point4,50);
    //cir1.Draw(painter);

    //绘制一个矩形
    CPoint point5(300,200);
    CRect crect (point2,point5);
    //crect.Draw(painter);
    
    //绘制一个在矩形内有圆的组合图形
    CPoint point6(175,150);
    CircleInRect cirrect(point6,50);
    //cirrect.Draw(painter);
	
	//实例化一个管理图形的对象,将所有图形加入管理,统一绘制,依靠多态来实现
    ShapeManager shapema;
    shapema.Add(&ctri);
    shapema.Add(&cir);
    shapema.Add(&cir1);
    shapema.Add(&crect);
    shapema.Add(&cirrect);
    shapema.Draw(painter);

    //shma.Add(&cir2);
    //shma.Draw(painter);

}

在这里插入图片描述
1:三角形, 2、3:圆形,4:矩形,5:复合图形

理解Add和Draw的实现原理,代码如下:

void ShapeManager::Add(CShape *pShape){
    m_pShape.push_back(pShape);
}

void ShapeManager::Draw(QPainter &painter){
    for(vector<CShape*>::iterator it = m_pShape.begin();it!=m_pShape.end();it++)
    {
        (*it)->Draw(painter);
    }

}

Add(CShape pShape)的形参为CSshape类型,根据类型兼容规则,基类的指针可用子类的指针赋值,同时避免不能访问到子类的成员,CShape的函数定义为虚函数式,那么在Draw(QPainter &painter)函数中,(*it)->Draw(painter);访问的Draw就是各子类中的重写的draw()。

2、图形类

1、关系图

在这里插入图片描述

2、CShape

class CShape
{
public:
    CShape();
    CShape(const CShape& shape);
    virtual ~CShape();
//    virtual double GetArea() const;
//    virtual bool ptIn(const CPoint& pt) const;
//    virtual bool InRect(const CRect& rc) const;
    virtual void Draw(QPainter &painter) const;
//    virtual void DrawColor();
//    virtual CShape* Clone() const;
//    virtual CShape& Move(int nOffsetX, int nOffsetY);

protected:
    string m_sName;
};

3、CPoint

class CPoint :virtual public CShape {
public:
    int m_nPosX;
    int m_nPosY;
    CPoint() {
        m_nPosX = 0;
        m_nPosY = 0;
    }
    CPoint(int nPosX, int nPosY);
    CPoint(const CPoint& pt);
    virtual ~CPoint();
//    double GetArea() const;
//    bool ptIn(const CPoint& pt) const;
//    bool InRect(const CRect& rc) const;
    void Draw(QPainter &painter) const;
//    void DrawColor();
//    CPoint* Clone() const;
//    CPoint& Move(int nOffsetX, int nOffsetY);
};

4、CTriangle

class CTriangle :virtual public CShape {
public:
    CTriangle() {}
    CTriangle(const CPoint& pt1, const CPoint& pt2, const CPoint& pt3);
    CTriangle(const CTriangle& tri);

    //CTriangle(const CPoint& pt);

    virtual ~CTriangle();
//    double GetArea() const;
//    bool ptIn(const CPoint& pt) const;
//    bool InRect(const CRect& rc) const;
    void Draw(QPainter &painter) const;
//    void DrawColor();
//    CTriangle* Clone() const;
//    CTriangle& Move(int nOffsetX, int nOffsetY);
    CPoint m_pts[3];
};

5、CRect

class CRect :virtual public CShape {
public:
    CRect() {}
    CRect(CPoint pt1, CPoint pt2);
    CRect(const CRect& rc);
    CRect(CPoint pt1);
    virtual ~CRect();
//    double GetArea() const;
//    bool ptIn(const CPoint& pt) const;
//    bool InRect(const CRect& rc) const;
    void Draw(QPainter &painter) const;
//    void DrawColor();
//    CRect* Clone() const;
//    CRect& Move(int nOffsetX, int nOffsetY);

    CPoint m_ptLT;
    CPoint m_ptBR;
};

6、CCircle

class CCircle:virtual public CShape {
public:
    CCircle() {}
    CCircle(CPoint ptCenter,double dR);
    CCircle(const CCircle& rc);

    CCircle(CPoint pt1);
    virtual ~CCircle();
//    double GetArea() const;
//    bool ptIn(const CPoint& pt) const;
//    bool InRect(const CRect& rc) const;
    void Draw(QPainter &painter) const;
//    void DrawColor();
//    CCircle* Clone() const;
//    CCircle& Move(int nOffsetX, int nOffsetY);

    CPoint m_ptCenter;
    double m_dR;
};

6、CircleInRect

class CircleInRect:public CCircle, public CRect {
public:
    CircleInRect() {}
    CircleInRect(CPoint ptCenter,double dR);
    CircleInRect(const CircleInRect& rc);

    CircleInRect(CPoint pt1);
    virtual ~CircleInRect();
//    double GetArea() const;
//    bool ptIn(const CPoint& pt) const;
//    bool InRect(const CRect& rc) const;
    void Draw(QPainter &painter) const;
//    void DrawColor();
//    CircleInRect* Clone() const;
//    CircleInRect& Move(int nOffsetX, int nOffsetY);

};

正在解决 在mainwindow添加一个shapemanager 来管理界面中的所有图形,shapemanager有vector<shape*>,然后将图形添加到shapemanager统一管理绘制,出现异常终止的问题。

原因:在paintEvent这个函数中,定义图形对象,将他们指针添加到shapemanager的vector中,相当于备份,那么paintEvent函数结束,其中定义的图形对象,生命周期也结束,但是这个vcetor中的指针备份未清除,而界面一直在刷新,paintEvent函数一直在重复执行,那么下次shma.Draw遍历访问的vcetor中的指针时,有无指向的指针,就会程序崩溃。

解决:
方法1、使用new的方法创建图形,同时记的removeall(),
方法2、图形对象不要定义在paintEvent中,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值