基于Qt Graphics View Framework的画图软件的实现思路

最近使用Qt开发了一个绘图软件,实现了拖动和放缩的功能。这里大体描述一下思路:

1、自定义类继承图形项:

    class MyItem : public QGraphicsItem

重写以下方法

    QRectF boundingRect()const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
    QPainterPath shape()const;

重写以下鼠标事件

    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
    void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);

2、自定义类继承视图:

    class MyView : public QGraphicsView 

重写以下事件

    //void paintEvent(QPaintEvent *pEvent);
    void mousePressEvent(QMouseEvent *mEvent);
    void mouseMoveEvent(QMouseEvent *mEvent);
    void mouseReleaseEvent(QMouseEvent *mEvent);

3、值得注意的地方:

(1)绘制放缩时候出现的皮筋效果:其实就是用虚线画出图形的外接矩形,为了区分图形是画好了,还是正在绘制中,可以加一个bool标记

(2)拖动和放缩:判断鼠标位置,在外接矩形边界上可以放缩,在矩形内部可以拖动,可以改变鼠标形状表现出来,也需要一个bool标记

(3)事件传递机制:由于视图和图形项都重写了鼠标事件,就会有一个问题,鼠标拖动等事件先从视图获得,然后传递到图形项,使用一个全局变量标记,这样

就不会出现图形项拖动带动视图中绘出内容

(4)坐标系的变换:在视图中绘制的图形坐标要变换到场景中去,由场景去负责图形项的管理,否则拖动的时候绘图会显示错位

(5)随笔画:继承item,写鼠标事件的时候,要注意判断点的位置,不能保证第一个点就在第二个点的左上方


目前界面大致如下:比较简单,菜单栏懒的写,工具栏只加了删除Action


目前实现的功能如下:

可以通过选择图形,然后在画布上拖动鼠标绘制简单几何图形,比如:直线,椭圆,矩形,一般四边形,五边形,六边形;

可以选中图形,进行移动;

可以通过图形四边进行放缩;

可以删除选中的图形,可以清空整个画布;

可以随笔涂鸦,画任何曲线,写字;

可以更换画笔的类型和大小;

可以更改画笔和填充颜色。


目前存在的问题如下:

程序结构不合理,把scene放在view里面,作为成员变量,明显不科学;view里面控制item的加减不符合实际。

更好的思路是自定义一个类继承QWidget,作为QMainWindow的中央控件,然后把scene和view都放进去。

继承view,重写view的事件不合理,最后重写widget的鼠标事件。

继承item,本身合理,但是应该把图形的属性分开单独设计图形类,然后把图形对象作为成员,沟通view和item的思路不合理,要用信号和槽。

删除有一个bug,那就是删除所有的item以后,再次添加会不显示,没有调试,虽然现在使用hack的方式解决了,但是习惯不好,不合理。


所犯过的低级错误:

以为写view的paint事件就能在view上显示,太天真,view显示的东西还是item绘制的,view只是一个媒介。

有人把scene比喻成黑板,item比如在黑板上画的图形或者写的字,而view呢,只相当于一个照相机,把黑板上的字照下来,给你看罢了。

另外,一个c++的傻逼错误,居然用指针共享对象,然后指针被后面的操作改变了,都没有发现,调试半天。








©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页