基础画板的插件化改造

基础画板的问题

上文写出的基础画板可以发现很多问题,假如将它实际应用在生产环境中会发现维护和后续开发可能会遇上麻烦。

controller和graph的耦合

graphcontroller类中定义了shape枚举用于储存当前绘制的形状,但是本质只是将已知的形状手动编号,在增改形状时不仅要删改形状本身,还要修改graphcontroller类中的内容,并且这两者是需要在源代码中手动保持一致的,这导致后续对代码的修改变得极为麻烦且易出问题。

谜语人文件编码

问题症结与上面类似,在文件读写之中采用编号制度储存形状,这在版本更迭时难以保证兼容性,故应为每个形状添加唯一的标识名称。

形状难增删

原因其中之一就是上文说的组件的耦合,另外mainwindow的按钮组件与图形切换的触发机制导致每个单独的形状都需要重新编写一个槽函数以及设置一堆QToolBar属性。

绘图流程死板

鼠标事件的处理放在了GraphController中统一进行,不方便加入其他类型的绘画,比如绘制多边形。

问题的解决方案

graphbase作为静态库独立,每个形状将其继承并编写为单个dll文件,即写成一个Qt插件。这样controller和graph之间通讯时必须由前者通过后者的接口获取信息并动态创建管理组件。

每个形状有一个唯一标识字符串,并应用于文件的保存读取中。

具体实现

静态库GraphPluginBase

作为画画的图形,也就是插件的基类。该类里面定义了形状的基本操作,鼠标的操作状态和命令枚举和鼠标事件函数。所有插件即dll的编写应继承自这个类。

插件

每个插件包含了一个形状。在头文件中声明了形状的大写和小写名称作为唯一标识符,重载了一些功能函数和鼠标事件函数。注意paint函数在每个插件里面都需要重载,因为每个形状的绘图逻辑不一样;每个形状应该根据自己的绘图流程重载鼠标事件函数。插件的导出函数有三个,类实例的新建函数、名称获取函数和QAction的获取函数。实际上如果要使代码更加简洁可以将后两者都写到基类里面去。

绘图控制类GraphController

绘图控制类GraphController主要作用是接收鼠标事件和控制图形行为,是MainWindow的子组件。类中包含插件和图形的QMapQList,存储了当前已经绘制的图形和已经导入的插件。类接收鼠标事件并根据鼠标时间发生的坐标将事件分发给相应的图形,如何反应又由图形本身决定。

主窗体MainWindow

主窗体主要控制窗体gui插件以及主导插件导入工作,使用了大量信号和槽。

形状容器ShapeContainer

主要用于主窗体选择形状信号的分发以及形状名称的临时保存。

成品效果