Quick-Cocos2d-x中,ListView:pushBackCustomItem()以及Widget:Clone(),均会导致模板控件中事先保存的自定义属性消失。这使得我们要每次克隆时需重新获取子控件引用。本文提供一个解决方案。
问题描述
使用ListView时,通常有两个部分,一个是List容器本身,另一个是子项模板Templete。Templete上有一些控件与数据相关联,比如背包物品的图标(ImageView)、数量(Label)等。下面以clone方案为例,假设有一个面板PanelBag.json,它里面有一个名为lstItem的ListView;另外有一个背包项widgetItem.json,它里面有一个lbName的Label用于标识物件名称。
理想的写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
functionPanelBag:initialize()
self._widget=GUIReader:shareReader():widgetFromJsonFile(
"res/PanelBag.json"
)
self._lstItem=self._widget:getChildByName(
"lstItem"
)
self:addWidget(self._widget)
self._tplItem=GUIReader:shareReader():widgetFromJsonFile(
"res/widgetItem.json"
)
self._tplTest._lbName=self._tplTest:getChildByName(
"lbName"
)
self:addTest(
"one"
)
self:addTest(
"two"
)
self:addTest(
"three"
)
end
functionPanelBag:addItem(name)
localwidgetItem=self._tplItem:clone()
widgetItem._lbName:setText(name)--nil错误,_lbName引用丢失
self._lstItem:pushBackCustomItem(widgetItem)
end
|
改进
如果在clone之后重新用getChildByName获取一次子控件,一旦Item项变得多,并且子控件更加复杂时,瞬间速度受收到影响。下面是改进方案。
1
2
3
4
5
6
7
8
|
functionPanelBag:addItem(name)
localwidgetItem=self._tplItem:clone()--拷贝C++数据
localpeer=tolua.getpeer(self._tplItem)--拷贝peertable
tolua.setpeer(widgetItem,peer)
widgetItem._lbName:setText(name)--_lbName已经可以访问了
self._lstTest:pushBackCustomItem(widgetItem)
end
|
原理
C++函数Widget::clone()的返回值是一个usertype,lua中对ussertype的扩展通过peertable实现。也就是说clone调用后,我们获得的是_tplTest丢弃了peertable的干净拷贝,这也是_lbName引用丢失的原因。那么只需将_tplTest的peertable赋予新的widgetItem就可以还原引用。
优点
来源网址:http://www.lolofinil.com/2014/07/22/quickx_widget_ext_clone/