画节点和线似乎是这个程序最基础的部分,看一下效果图:
节点目前是从左边拖出来的图片,然后组成一个QGraphicsPixmapItem
,线是按下键盘i
键后,光标切换为十字,在两个节点处连线。关于画节点我之前一篇文章有过介绍:Qt实现图片可拖拉 实际实现过程中使用的是另一种方式:
这张图一目了然,节点实际上是在images目录下读取的图片文件,构成QListWidgetItem
,在构成的过程中存入该图片的路径,当移动该item
时,将路径存入QMimeData
,scene拿到该路径构建CustomPixmapItem
,最终加入到scene中。
而关于画线,不仅要在两个节点之间画线,更重要的是,节点在移动时,线也要跟着移动。视觉上呈现这跟线就是和节点绑定的,节点到那线到那的效果。
(这个问题之前一直很困扰我,因为我虽然可以在两个节点之间画线,但线的更新操作逻辑很复杂,而且程序经常崩溃,我当时是在scene中拿到要移动的节点周围的所有线,更新线的两个端点。在更新之前记下移动的节点的点point,这样就能知道这跟线的哪个点位置变化了。这个逻辑不仅看起来麻烦,实现起来也很复杂。看看我现在是怎么做的?)
直观的角度,每个节点记录下与自身相连的线,每条线记录下相连的两个节点。如果节点移动,节点通知与自身相连的线更新位置,线收到更新指令后,将自身位置更新为记录的两个端点的位置。 清晰明了。再深入,节点可以将与自身相连的线,分为两部分,即出向的线、入向的线。
看一下实现代码:
pixmapitem中确实有两个vector分别保存入向和出向的线
lineitem中确实保存了两个节点
pixmapitem位置发生变化时,遍历两个线vector,更新线。
线更新时,直接取pixmapitem的位置信息,重新setLine
。
更新操作完成。
再来看一下画线的过程:
可以看到,m_pGraphcsLineItem
只是为了用来展现画线的过程,实际画的线是CustomLineItem
,并且在构造线时传入两个端点。两个端点保存与自身相连的线,对pStartItem
来说,这根线就是item出向的线,对pEndItem
来说,这根线就是item入向的线。
这便是画线以及更新线的过程,逻辑清晰明了。而且节点分两部分保存入向和出向的线时,可以很方便的知道以该节点作为起点的线有哪些!