六、实体管理(QTreeWidget、QFileDialog)
这一节的内容相对来说比较多,但是依然是很简单,只不过因为我们要求的操作比较多,制作起来比较麻烦一点而已。最后成品如下图:
在开始之前先把实体管理的XML表确定下来。暂时定了以下结构:
用名字字符串还是ID,这是个很纠结的问题,不过只是使用编辑器的话那倒无所谓,编辑器在乎的是其稳定性与实用性,效率只要不是太差,一般都能接受(有些商业引擎编译时间那是相当地长啊)。
根据XML表就可以确定树型结构的层次,这种简单的实体管理把层级设定超过两层,简直就是找抽行为。
完成XML表后,现在来分析更细的需求:
1、工具栏:实体管理还有一些常用操作,我把它们分为添加组,删除组,添加实体,删除实体,清空组,清空所有。
2、编辑修改:组这一层不支持从文件中提取,只能由工具栏添加,所以我们要支持双击修改保存文字,实体则是由文件对话框添加的,以后配合好属性栏,就能很方便的修改,所以不需要双击编辑修改。
3、右键菜单:组这一层对应的操作应该是添加实体,删除组,清空组,而实体这一层则只有删除实体这个选项。
4、图标:工具栏肯定需要图标,组和实体前面也需要一个图标,不然看一堆文字很不舒服。
5、拖放:实体可以拖到另一个组。
需求确定后,首先按照上一节的方法新建一个Dock Widget,命名为m_pEntityDock。并把它的可挂接的位置,设为左,右,下三个区域,默认区域设为左侧。
然后我们添加一个新类,类名叫EntityViewWidget,继承于QWidget,构造函数接受父类指针,并把它赋给Qwidget。
类申明如下:
先按照第四节的方法在里面创建一个QToolBar,并添加6个基于图标的QAction,并按照上章QT基础里面介绍设定自定义Slot的方法,分别设定好公有Slot函数(SAddEntity、SRemoveEntity、SAddGroup、SRemoveGroup、SClearGroup、SClearAll),因为QT的函数使用的是小写字母开头的驼峰式,所以我把自定义的SLOT用S前缀命名,以免混淆,而普通函数则是大写字母开头,注:这种命名方式并不一定是最好的命名方式。
Slots中有一个SSelectionChanged(),这是针对QTreeWidget的信号itemSelectionChanged的槽,因为添加删除操作和当前选中的item相关联,在这个Slot里面就添加了选中处理代码。
MAX_GROUP_COUNT指的是允许的最大组数。因为QTreeWidget只是指向指针,所以要申请空间给QTreeWidgetItem,这里使用了预分配机制,配合一个int型的m_nGroupCount来避免遍历的工作,这个具体在后面再说。
留了两个指针分别表示当前选中的组和实体,之所以把它们分开是因为有可能会同时用到两个。
EntityTreeWidget是自定义的QTreeWidget,类申明如下:
把这个类放在EntityViewWidget类的上面,因为需要在这个类中调用一些EntityViewWidget的方法。
因为需求,所以重载了一些QTreeWidget的事件,这也是使用自定义TreeWidget的主要原因,它们用来处理按键、拖动、上下文菜单,另外还自定义了一个Slot,用来解决编辑后的反馈。
再来看EntityTreeWidget的实现,代码如下: