一:
先来看一下界面的截图:
![](https://i-blog.csdnimg.cn/blog_migrate/88d7e0ec913cfb099ea458a878f3d108.png)
说明:
拖动节点的时候,与该节点相关的箭头连线也会跟着调整;
用户可以使用鼠标从一个节点拖出一个箭头到另一个节点(鼠标在空白区域点击一下,拖出的箭头消失)
![](https://i-blog.csdnimg.cn/blog_migrate/e173a71196920a4e6fe04eb55dc9ac07.png)
这三个图标,手型图标处于选中状态的时候,节点可以拖动,
箭头图标处于选中状态的时候,可以使用鼠标绘制连线箭头
最后一个图标,用于在画布上创建一个节点方框
二:
关键代码文件如下图(用红框框住的为关键代码文件)
![](https://i-blog.csdnimg.cn/blog_migrate/85bd7940d7458cf6f8f9ae17e21083d0.png)
其他文件均为辅助代码文件(有些文件中的代码没有用到)
三:
CustomView类是我们的绘图面板,这个类继承自
QGraphicsView
在这个类的构造函数中,我们创建了他的
QGraphicsScene
![](https://i-blog.csdnimg.cn/blog_migrate/914ec3ab665f60e5273079c34cb20fb6.png)
并设置了它的大小(这也是为什么我们的绘图板有滚动条的原因)
另外需要注意的是QGraphicsScene的坐标原点在中心位置,如下图所示
boundingRect是
QGraphicsItem的虚函数,必须要实现,
![](https://i-blog.csdnimg.cn/blog_migrate/b5d92675a52426952457eb0ced713a6f.png)
四:
CustomArrow是描述箭头连线的类:
这个类继承自
QGraphicsItem
![](https://i-blog.csdnimg.cn/blog_migrate/a2dc20340350b7acd3bf8e9bd6de41a7.png)
其中1.5是箭头连线的线宽,8是箭头张开后所占的区域宽度
p1是箭头的起始点,p2是箭头结束点(也就是带箭头的那一端)
最终返回的一个Rect结构如下图所示:(注意箭头的起点,在上一个方框的中心点上)
![](https://i-blog.csdnimg.cn/blog_migrate/b5b6eae5e23288e82846629bfe98c1f3.png)
五:
我给CustomArrow类公开了一个adjust函数,旨在当方框节点移动的时候,重新计算箭头的起始位置、结束位置、箭头的角度
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/232fb5123d76666187cf6e78e68d9e81.png)
其中:itemA是起始处的方框节点,itemB是结束处的方框节点
注意mapFromItem是把方框节点中心点映射到scene坐标系中
紧接着的if,else是为了判断起始方框是否位于结束方框的下方,如果是,那么箭头的终点应该在结束方框的下边框上
接下来是计算出箭头的两个点arrowP1和arrowP2
六:
绘制箭头的工作是在CustomArrow的paint函数中完成的,代码如下所示
![](https://i-blog.csdnimg.cn/blog_migrate/203eab019a8957169a60009a40fbb66a.png)
箭头只不过是一个多边形,用drawPolygon画出来的
七:
CustomRect继承自
QGraphicsRectItem
在这个类型中,我们重载了itemChange函数,代码如下
![](https://i-blog.csdnimg.cn/blog_migrate/280962ee53f456c262a374386012da95.png)
当当前方框节点移动后,与这个节点相关的箭头都要跟着移动
Arrows就是与当前方框节点有关的箭头
八:
在来看一下CustomRect的MousePressEvent的代码
![](https://i-blog.csdnimg.cn/blog_migrate/f88c137f1b5d6588105178cf1d4b874b.png)
在这个代码中,
我们先为全局标志ScenClickFlag赋值,
这个标志着当前点击的是一个方框节点,还是点击在画布的空白处了
接下来判断箭头按钮是不是处于选中状态
再往下判断是不是已经记录了起始方框,如果没记录,那么就记录并返回
再接下来,就意味着用户是点击的结束方框,这时要绘制一个箭头了,
当然首先要判断是不是已经存在了同样的箭头,如果存在了,就没必要再绘制了,
ScenClickFlag置成true是为了冒泡触发画布的点击事件(后续会讲为什么要允许事件冒泡)
接下来执行了绘制箭头的逻辑,并在起始节点和结束节点分别记录了箭头的指针
以后这两个节点移动的时候,箭头也会跟着移动了。
未完待续,喜欢的话请点推荐(您的支持,是我的动力)--------------------->
代码会在下一篇文章中发布