很高兴,今天我搞定了我很久没有搞定的问题,那种很久没有过的很爽的感觉又来了,感觉:“爽!”。
当然,我写这个blog当然不是为了表达我的“爽”,只是我需要记录一下这个开发过程中遇见的问题,以便以后借鉴。
开发项目介绍:我的项目就是要开发一个类似eclipse中navigator一样导航视图,我叫它“visual control block editor view”。 这个view和eclipse的view一样是依据底层文件系统的,但和eclipse视图不同的是,我的view并不显示eclipse的workspace中的所有project,而只显示我关心的project,于是我采取的方法就是运用CNF(Common Navigator Framework)来进行eclipse扩展。继承CommonNavigator作为view的视图类,重写它的初始输入,将其定义为自己想要的输入,(eclipse默认的输入是workspaceRoot,也就是workspace目录),然后定义自己的contentProvider和labelProvider,这样一个自己定义的view就出来了。
那么下面的问题就来了,给view中treeItem加右键菜单。我的菜单主要又new,copy,paste,delete,refresh。其中copy,paste由于需要共用到clipboard,所以我将他们定义到一个actiongroup中,然后利用actionProvider扩展来提供扩展,然后对refresh按钮,根据我从同事那里得到的经验,是只需要直接调用Viewer.refresh()就能达到要求了,然而,问题出现了...
就在我直接调用Viewer.refresh()并希望能达到我想要的刷新效果的时候,郁闷的事情发生了,view确实被刷新了,可是它不能维持住它刷新前的展开状态(expand state),然后我再去请教师兄,师兄告诉我说,他就是那么直接调用的,可是他就达到效果了。郁闷……,难道是rp问题???我不相信,我rp一直好啊……,最后,师兄告诉我说,因为他不清楚我做的东西,但他告诉我,是不是跟我用的自己的datamodel有关。
什么是datamodel? 好比在eclipse中,它的navigator视图中的每一个TreeItem就代表了一个IResource,这个就是它的datamodel,由于功能需求,我需要对不同级别的IFolder做不同的右键菜单,所以我就不能直接用eclipse的datamodel了,于是我就定义了我自己的datamodel,叫做“IIfaResource”。
师兄的提醒并没有引起我的注意,因为我不是很理解,于是我在bbs上跪求大牛们教我解决之道,因为我把问题归结为是SWT中TreeItem的getItems()和getExpanded()方法的问题,于是我想请大牛们教我这两个方法的实现原理,因为我看不懂。结果大牛们给我的答案是:“大哥,要看源码也不用看SWT的吧”,于是我决定自己来研究源码,最后我把问题归结为系统平台问题。于是就在昨天,我觉得我无法解决这个问题了,如果我还是要调用Viewer.refresh()的话。
于是,今天早上一开电脑我就打算好开辟一条新的解决问题的路,我的想法就是我自己写代码覆盖getExpanded()方法,然后我做到了,refresh能够维持展开状态了。我兴奋……
偶然的机会,让我调试的时候进入道了一个哈希表的containKey()方法中看了下,发现它调用了一个Object.hashcode()方法,eclipse的IResource是覆盖了这个方法的,但是我的IIfaResource却没有,于是我重新想起了我的同事当初对我说的,“是不是你定义的datamodel有没有没有实现的接口???”,我抱着侥幸的态度,在我定义的datamodel(IIfaResource)中覆写了hashcode()方法,然后继续固执的调用Viewer.refresh()方法,奇迹出现了……, It works!!!!!!!!
就这样,我的Navigator Tree Version 5诞生了。
点醒了我:code的时候如果想要定义自己的数据类型,就要考虑哪些是需要覆写的方法,比如:hashcode(), equals(), toString()等等。
点醒了我:在使用组件或者用framework编码的时候,如果为了需求的需要,替换了组件或者framework本身的一些数据类型,而当调用组件或者framework本身提供的api却达不到理想中的效果的时候,“怀疑组件或者framework定义的不够好,或者封装的不够好,对数据类型有依赖性”的态度是勇敢的,是鼓励的,但同时,希望还是考虑一下是不是自己的数据类型没有将组件或者framework中数据类型定义的那些必须实现的接口实现,以至于组件或者framework在底层调用的时候找不到相应的代码而直接上型到Object。从而出错。 毕竟因为后者的可能性比较大…… :-)
当然,我写这个blog当然不是为了表达我的“爽”,只是我需要记录一下这个开发过程中遇见的问题,以便以后借鉴。
开发项目介绍:我的项目就是要开发一个类似eclipse中navigator一样导航视图,我叫它“visual control block editor view”。 这个view和eclipse的view一样是依据底层文件系统的,但和eclipse视图不同的是,我的view并不显示eclipse的workspace中的所有project,而只显示我关心的project,于是我采取的方法就是运用CNF(Common Navigator Framework)来进行eclipse扩展。继承CommonNavigator作为view的视图类,重写它的初始输入,将其定义为自己想要的输入,(eclipse默认的输入是workspaceRoot,也就是workspace目录),然后定义自己的contentProvider和labelProvider,这样一个自己定义的view就出来了。
那么下面的问题就来了,给view中treeItem加右键菜单。我的菜单主要又new,copy,paste,delete,refresh。其中copy,paste由于需要共用到clipboard,所以我将他们定义到一个actiongroup中,然后利用actionProvider扩展来提供扩展,然后对refresh按钮,根据我从同事那里得到的经验,是只需要直接调用Viewer.refresh()就能达到要求了,然而,问题出现了...
就在我直接调用Viewer.refresh()并希望能达到我想要的刷新效果的时候,郁闷的事情发生了,view确实被刷新了,可是它不能维持住它刷新前的展开状态(expand state),然后我再去请教师兄,师兄告诉我说,他就是那么直接调用的,可是他就达到效果了。郁闷……,难道是rp问题???我不相信,我rp一直好啊……,最后,师兄告诉我说,因为他不清楚我做的东西,但他告诉我,是不是跟我用的自己的datamodel有关。
什么是datamodel? 好比在eclipse中,它的navigator视图中的每一个TreeItem就代表了一个IResource,这个就是它的datamodel,由于功能需求,我需要对不同级别的IFolder做不同的右键菜单,所以我就不能直接用eclipse的datamodel了,于是我就定义了我自己的datamodel,叫做“IIfaResource”。
师兄的提醒并没有引起我的注意,因为我不是很理解,于是我在bbs上跪求大牛们教我解决之道,因为我把问题归结为是SWT中TreeItem的getItems()和getExpanded()方法的问题,于是我想请大牛们教我这两个方法的实现原理,因为我看不懂。结果大牛们给我的答案是:“大哥,要看源码也不用看SWT的吧”,于是我决定自己来研究源码,最后我把问题归结为系统平台问题。于是就在昨天,我觉得我无法解决这个问题了,如果我还是要调用Viewer.refresh()的话。
于是,今天早上一开电脑我就打算好开辟一条新的解决问题的路,我的想法就是我自己写代码覆盖getExpanded()方法,然后我做到了,refresh能够维持展开状态了。我兴奋……
偶然的机会,让我调试的时候进入道了一个哈希表的containKey()方法中看了下,发现它调用了一个Object.hashcode()方法,eclipse的IResource是覆盖了这个方法的,但是我的IIfaResource却没有,于是我重新想起了我的同事当初对我说的,“是不是你定义的datamodel有没有没有实现的接口???”,我抱着侥幸的态度,在我定义的datamodel(IIfaResource)中覆写了hashcode()方法,然后继续固执的调用Viewer.refresh()方法,奇迹出现了……, It works!!!!!!!!
就这样,我的Navigator Tree Version 5诞生了。
点醒了我:code的时候如果想要定义自己的数据类型,就要考虑哪些是需要覆写的方法,比如:hashcode(), equals(), toString()等等。
点醒了我:在使用组件或者用framework编码的时候,如果为了需求的需要,替换了组件或者framework本身的一些数据类型,而当调用组件或者framework本身提供的api却达不到理想中的效果的时候,“怀疑组件或者framework定义的不够好,或者封装的不够好,对数据类型有依赖性”的态度是勇敢的,是鼓励的,但同时,希望还是考虑一下是不是自己的数据类型没有将组件或者framework中数据类型定义的那些必须实现的接口实现,以至于组件或者framework在底层调用的时候找不到相应的代码而直接上型到Object。从而出错。 毕竟因为后者的可能性比较大…… :-)