威尼斯www.9778.com-威尼斯正版官方网站

被控件Zorder难点烦扰几天

日期:2019-12-25编辑作者:编程人生

图片 1

第九章 、 TreePanel

我们做iOS开发是一定会有很多的页面跳转,用代码写是不是很烦呢,特别使我们已经了解storyboard的方便,但有时候跳转是必要的要向下一个页面传送很多数据,所以我们又不得不用代码写,这是一个问题。

界面是tree控件在几个text前面,但我点击tree的空白处后面的几个text就会出来,网上搜了N多方法,ctrl+d改过,rc文件也把tree顺序放过最前面、最后面都不管用,求老司机帮我支个招我的ide是vc6.0,没办法代码比较老只能在vc6.0下跑

 

解决:- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

9.1 、 TreePanel之基本使用

这个方法是使用storyboard连线跳转是触发的其中参数segue表示我们跳转连的那根线,他有几个属性:@property (nonatomic, readonly) NSString *identifier;                 唯一标识,用于好几个线一起时,区分谁是谁。

在 应用程序中,我们经常会涉及到要显示或处理树状结构的对象信息,比如部门信息、地 区
信息,或者是树状的菜单信息,操作系统中的文件夹信息等。
对于传统的 html 页面来说,要自己实现显示树比较困难,需要写很多的 javascript ,特
别是对于基于 Ajax 异步加载的树来说,不但涉及到 Ajax 数据加载及处理技术,还需要考 虑
跨浏览器支持等,处理起来非常麻烦。 ExtJS 中提供了现存的树控件,通过这些控件可以 在
B/S 应用中快速开发出包含树结构信息的应用。
TreePanel TreePanel TreePanel 基本使用
树控件由 Ext.tree.TreePanel 类定义,控件的名称为 treepanel , TreePanel 类继承自 Pane l
面板。在 ExtJS 中使用树控件其实非常简单,我们先来看下面的代码
Ext.onReady(function(){
var root=new Ext.tree.TreeNode({
id:"root",
text:" 树的根 "});
root.appendChild(new Ext.tree.TreeNode({
id:"c1",
text:" 子节点 "
}));
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:100
});
});

@property (nonatomic, readonly) id sourceViewController;          原页面,就是线的开始端

 

@property (nonatomic, readonly) id destinationViewController;    跳转页面, 线的结束段

代码的第一句使用 new Ext.tree.TreeNode 类来创建一个树节点,第二句使用树节点的
root 的 appendChild 方法来往该节点中加入一个子节点,最后直接使用 new Ext.tree.TreePan el
来创建一个树面板,要树面板的初始化参数中指定树的 root 属性值为前面创建的 root 节点 ,
也就是树根节点。上面的程序执行效果如下图所示:
树的节点信息。 ExtJS 的树控件提供了对这种功能的支持,你只需要在创建树控件的 时
候,通过给树指定一个节点加载器,可以用来从服务器端动态加载树的节点信息。我们来 看
下面的代码:

补:identifier的值可以在storyboard上点击线编辑

var root=new Ext.tree.AsyncTreeNode({
id:"root",
text:" 树的根 "});
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
loader: new Ext.tree.TreeLoader({url:"treedata.js"}),
width:100
});

使用实例:

 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

treedata.js 这个 url 返回的内容如下:
[{
id: 1,
text: ' 子节点 1',
leaf: true
},{
id: 2,
text: ' 儿子节点 2',
children: [{
id: 3,
text: ' 孙子节点 ',
leaf: true
}]
}]

if ([segue.identifier isEqualToString:@"segueInformation"]) {

 

}

执行上面的程序,可以得到一棵异步加载子节点的树,点击 “ 根节点 ” 会到服务器端 加
载子节点,如下图所示:
当然上面的程序是一次性加载完了树的所有节点信息,我们也可以实现让每一个节点 都
支持动态加载的树,只需要在通过服务器请求数据的时候,每次服务器端返回的数据只只 包
含子节点,而不用把孙子节点也返回即可。比如把上面 treedata.js 中的内容改为下面的内 容 :
[{
id: 1,
text: ' 子节点 ',
leaf: false
}]

if ([segue.identifier isEqualToString:@"shoppingcartDe"]) { //判断是那条线

 

BMCLSingleDetailsViewController *vc = segue.destinationViewController;//找到目的页面,有目的页面就可以随意传数据了不是吗?

也就是节点树中只包含一个子节点,而该子节点通过指定 leaf 值为 false ( 默认情况该 值
为 false) ,表示该节点不是一个叶子节点,其下面还有指节点。再执行前面的程序,不断点
击 “ 子节点 ” 可以得到如下图所示的效果:
当然这是一个无限循环的树,在实际应用中我们服务器端返回的数据是程序动态产生的,因此不可能每一次都产生 leaf 为 false 的节点,如果是叶子节点的时候,则需要把返回
的 JOSN 对象中的 leaf 设置为 true 。如下所示:
[{
id: 1,
text: ' 子节点 ',
leaf:true
}]

vc.shopId=sender;

 

}

事件处理
当然,仅仅能显示一棵树还不够,我们一般还需要在用户点击树节点的时候执行相应 的
东西,比如打开某一个连接,执行某一个函数等,这就需要使用到事件处理。比如下面的 代
码:
Ext.onReady(function(){
var root=new Ext.tree.TreeNode({
id:"root",
text:" 树的根 "});
var c1=new Ext.tree.TreeNode({
id:"c1",
text:" 子节点 "
});
root.appendChild(c1);
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:100
});
tree.on("click",function(node,event){
alert(" 您点击了 "+node.text);
}
);
c1.on("click",function(node,event){
alert(" 您点击了 "+node.text);
}
);
});

if ([segue.identifier isEqualToString:@"segueDJJ"]) {

 

NSString *strID=@"";

执行上面的程序,当用户点击树控件中的任意节点时,都会弹出一个提示信息框,当
用户点击 c1 这个子节点时,会弹出两次提示信息框。因为我们除了指定 tree 的 click 事件 响
应函数以外,另外又给 node 节点指定单独的事件响应函数。
当然,如果只是要实现当点击树节点时跳到某一个指定 url 的功能则非常简单。看下 面的代码:
Ext.onReady(function(){
var root=new Ext.tree.TreeNode({
id:"root",
href:"",
hrefTarget:"_blank",
text:" 树的根 "});
var c1=new Ext.tree.TreeNode({
id:"c1",
href:"",
hrefTarget:"_blank",
text:" 子节点 "
});
root.appendChild(c1);
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:100
});
});

for (GeneralMode *mode in _arrDataSoucre) {

 

strID= [strID stringByAppendingString:@","];

执行程序,点击树节点,将会在浏览新窗口中打开节点中 href 指定的链接。

strID= [strID stringByAppendingString:mode.ID];

 

strID= [strID stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""];

9.2 、 TreeNode

}

 

BMCLVoucherViewController *vc=segue.destinationViewController;

在 ExtJS 中,不管是叶子节点还是非叶子节点,都统一用 TreeNode 表表示树的节点。
在 ExtJS 中,有两种类型的树节点。一种节点是普通的简单树节点,由 Ext.tree.TreeNode 定
义,另外一种是需要异步加载子节点信息的树节点,该类由 Ext.tree.AsyncTreeNode 定义。 看
下面的代码:
Ext.onReady(function(){
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:new Ext.tree.AsyncTreeNode({
text:" 根节点 "
}),
width:100
});
});

vc.strGoodIDlist=strID;

 

[vc setBlockBackpric:^(CGFloat pric,NSString *strIdDJJ) {

执行程序,点击树中的 “ 根节点 ” 则会一直发现树会尝试加载这个节点的子节点,由 这里没有指定树的加载器,所以 “ 根节点 ” 会变成一直处于加载的状态。如下图所示:
对于普通的 TreeNode 来说,可以通过调用节点的 appendChild 、 removeChild 等方法来
往该节点中加入子节点或删除子节点等操作。
TreeNode 与 AsyncTreeNode 可以同时使用,比如下面的代码:
Ext.onReady(function(){
var root=new Ext.tree.TreeNode({
id:"root",
text:" 树的根 "
});
var c1=new Ext.tree.TreeNode({
text:" 子节点 1"
})
var c2=new Ext.tree.AsyncTreeNode({
text:" 子节点 2"
});
root.appendChild(c1);
root.appendChild(c2);
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:300,
loader:new Ext.tree.TreeLoader({
applyLoader:false,
url:""
})
});
});

_labDJJPirc.text=[NSString stringWithFormat:@"-¥%.2f",pric];

 

_strIdDJJ=strIdDJJ;

treedata.js 中的内容仍然是:
[{
id: 1,
text: ' 子节点 '
}]

[self setMoney:pric];

 

}];

执行上面的程序可以得到一棵如下图所示的树:

}

ExtJS 实用简明教程
另外要在树以外的程序中得到当前选择的节点,可以通过 TreePanel 的
getSelectionModel 方法来获得,该方法默认返回的是 Ext.tree.DefaultSelectionModel 对象,
DefaultSelectionModel 的 getSelectedNode 方法返回当前选择的树节点。比如要得到树 tree 中
中当前选择节点,代码如下:
tree.getSelectionModel().getSelectedNode()

if ([segue.identifier isEqualToString:@"segueQDaddress"]) {

 

if (_modeAddress.ID.length == 0) {

9.3 、 TreeLoader

BMVLAddAddressViewController * vc = [self.storyboard instantiateViewControllerWithIdentifier:NSStringFromClass([BMVLAddAddressViewController class])];

 

[self.navigationController pushViewController:vc animated:YES];

对于 ExtJS 中的树来说,树加载器 TreeLoader 是一个比较关键的部件,树加载器由
Ext.tree.TreeLoader 类定义,只有 AsyncTreeNode 才会使用 TreeLoader 。看下面的代码:
Ext.onReady(function(){
var loader=new Ext.tree.TreeLoader({
url:""
});
var root=new Ext.tree.AsyncTreeNode({
id:"root",
text:" 根节点 ",
loader:loader});
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:100
});
});

}else{

首先我们使用 Ext.tree.TreeLoader 来初始化了一个 TreeLoader 对象,构造函数中的配 置
数 url 表示获得树节点信息的 url 。然后在初始化根节点的时候我们使用的是
ncTreeNode ,在该节点中指定该节点的 laoder 为前面定义的 loader 。执行这段程序,在
击 “ 根节点 ” 时,会从服务器端指定 root 节点的子节点信息。
TreeLoader 严格来说是针对树的节点来定义的,可以给树中的每一个节点定义不同的
eLoader ,默认情况下,如果一个 AsyncTreeNode 节点在准备加载子节点的时候,如果 该
点上没有定义 loader ,则会使用 TreePanel 中定义的 loader 作为加载器。因此,我们可以
接在 TreePanel 上面指定 loader 属性,这样就不需要给每一个节点指定具体的 TreeLoader
。因此,上面的代码可以改成如下所示的内容 :

BMCLMyaddressViewController *vc=segue.destinationViewController;

 

vc.shoppingSign=@"123456";

 

vc.orderSIgn=_modeAddress.ID;

9.3  、 TreeLoader

vc.blockShoopingChart=^(GeneralMode *mode){

 

_defaultTips.hidden=YES;

对于 ExtJS 中的树来说,树加载器 TreeLoader 是一个比较关键的部件,树加载器由
Ext.tree.TreeLoader 类定义,只有 AsyncTreeNode 才会使用 TreeLoader 。看下面的代码:
Ext.onReady(function(){
var loader=new Ext.tree.TreeLoader({
url:""
});
var root=new Ext.tree.AsyncTreeNode({
id:"root",
text:" 根节点 ",
loader:loader});
var tree=new Ext.tree.TreePanel({
renderTo:"hello",
root:root,
width:100
});
});

_labArea.text=[NSString stringWithFormat:@"%@ %@ %@",mode.provinceid,mode.cityid,mode.districtid];

 

_labDetlAddress.text=mode.detail;

首先我们使用 Ext.tree.TreeLoader 来初始化了一个 TreeLoader 对象,构造函数中的配 置
参数 url 表示获得树节点信息的 url 。然后在初始化根节点的时候我们使用的是
AsyncTreeNode ,在该节点中指定该节点的 laoder 为前面定义的 loader 。执行这段程序,在
点击 “ 根节点 ” 时,会从服务器端指定 root 节点的子节点信息。
TreeLoader 严格来说是针对树的节点来定义的,可以给树中的每一个节点定义不同的
TreeLoader ,默认情况下,如果一个 AsyncTreeNode 节点在准备加载子节点的时候,如果 该
节点上没有定义 loader ,则会使用 TreePanel 中定义的 loader 作为加载器。因此,我们可以
直接在 TreePanel 上面指定 loader 属性,这样就不需要给每一个节点指定具体的 TreeLoader
了。因此,上面的代码可以改成如下所示的内容 :

_labNameAndPostCode.text=[NSString stringWithFormat:@"%@ %@",mode.nick_name,mode.post_code];

 

_labPhone.text=mode.receiver_phone;

9.4  自定义 TreeLoader

_modeAddress=mode ;

 

};

在 ExtJS 自己的 TreeLoader 中,当要实现从远程服务器端异步加载树节点信息的时候,
都是通过请求服务器上的某一个 URL 来进行的,这个 URL 返回下面的信息:
[{
id: 1,
text: 'A leaf Node',
leaf: true
},{
id: 2,
text: 'A folder Node',
children: [{
id: 3,
text: 'A child Node',
leaf: true
}]
}]

vc.blockDel=^(NSString *str){

 

_defaultTips.hidden=NO;

假如我们是直接通过类似 DWR 或 EasyJWeb 的远程脚本引擎在客户端直接调用服务器
的业务方法,直接跳过了 WEB (不需要 Struts 、 JSP 或其它 Web 层的代码)这一层,这时
我们没有 URL ,这时该怎么办呢?这就需要使用到自定义的 TreeLoader ,下面我们通过一
个实例来做简单的讲解。
看服务器端的 ITopicCategoryService
public interface ITopicCategoryService {
List loadCategory(Long id);
}

_labArea.text=@"";

 

_labDetlAddress.text=@"";

loadCategory 方法返回一个类型为 Node 的列表,也就是返回指定 id 的下级分类信节点
信息, Node 对应树节点的信息,代码如下:
public class Node {
private TopicCategory category;
Node(TopicCategory category) {
this.category = category;
}
public String getId() {
return category.getId().toString();
}
public boolean getLeaf() {

_labNameAndPostCode.text=@"";

return category.getChildren().size() < 1;
}
public String getText() {
return category.getName();
}
public String getQtip() {
return category.getName();
}
}

_labPhone.text=@"";

 

_modeAddress=nil;

Node 在这里相当于一个简单适配器,其实就是把数据库中的日志分类实体适配成包树
节点对象。
把 ITopicCategoryService 发布成可供客户端远程调用,使用 EasyJWeb 的话引如下面三
个 js :
<script type="text/javascript" src="/ejf/easyajax/prototype.js"></script>
<script type="text/javascript" src="/ejf/easyajax/engine.js"></script>
<script type="text/javascript" src="/ejf/easyajax/topicCategoryService.js"></script>

};

使用 DWR 的话引入下面的两个 js :
<script type="text/javascript" src="/dwr/dwr/engine.js "></script>
<script type="text/javascript" src="/dwr/dwr/util.js "></script>
<script type="text/javascript" src="/dwr/dwr/interface/ topicCategoryService.js "></script>

}

 

}

这样我们可以在页使用下面的 javascrpt 来从服务器端获得某一个节点的子节点信息,
代码如下:
function test()
{
topicCategoryService.loadCategory(1,function(ret)
{
alert(" 一共有 "+ret.length+" 个子节点 ");
}
}

if ([segue.identifier isEqualToString:@"segueQRFP"]) {

 

BMCLInvoiceViewController *vc=segue.destinationViewController;

如何让 ExtJS 的树面板能通过这个远程 web 脚本方法 topicCategoryService.loadCategory
来加载异步加载树节点信息呢?其实很简单,跟一般的使用没什么两样,树面板 TreePanel
的代码如下:

[vc setBlockBackInfo:^(GeneralMode *modeFP) {

var tree = new Ext.tree.TreePanel({
autoScroll:true,
animate:true,
width:'100px',
height:'300px',
enableDD:true,
containerScroll: true,
loader: loader
root: new Ext.tree.AsyncTreeNode({
text: ' 日志分类 ',
id:'root'
});
});

_modeFP=modeFP;

 

_labFPType.text=modeFP.strType;

然后区别是在 loader 部分,使用远程 Web 调用来加载树节点的 loader ,代码如下:
var loader=new WebInvokeTreeLoader({
fn:topicCategoryService.loadCategory
});
loader.on("beforeload",function(l,node){
l.args[0]=(node.id!='root'?node.id:"-1");
});

}];

 

}

再回顾一下传统的直接通过 url 加载树节点的 TreeLoader 代码,如下所示:
var loader=new Ext.tree.TreeLoader({
url:"
});
loader.on("beforeloader",function(loader,node){
loader.baseParams.id=(node.id!='root'?node.id:"");
});

 

区别在于,远程脚本调用方式加载树节点信息使用的是 WebInvokeTreeLoader ,需要通
过 fn 属性来指定用于加载数据的远程方法,并在 beforeload 事件处理器设置参数远程方法
调用的参数值。而传统的树节点加载器是 Ext.tree.TreeLoader ,需要指定一个 url 来获得 jso n
数据。
WebInvokeTreeLoader 是自定义的树加载器,代码其实比较简单,你可以自己写一个。 本
方案仅供参考,关于 WebInvokeTreeLoader 的源代码我已经传到了我用 ExtJS 开发的 Blog
示例网站上了,仅供 VIP 会员浏览,有兴趣的朋友可跟我联系。

本文由威尼斯www.9778.com发布于编程人生,转载请注明出处:被控件Zorder难点烦扰几天

关键词:

求助 cannot convert parameter 4 from &#x27;char [260]&#x27; to &#x2

CDatabasedb;charDB[MAX_PATH];sprintf(DB,"ODBC;DSN=User_odbc;UID="",PWD=""");//LPCTSTRch=(LPCTSTR)DB[MAX_PATH];//db.Open(NULL,FALSE,FALSE,ch);db.Open(NU...

详细>>

求助:MFC静态嵌套拆分窗口的问题

在初始分隔四个视图,然后左上视图是树状结构,通过节点改变左下和右下视图;;;;左下视图可以输入数字,并...

详细>>

关于CString CtrlList::GetItemText返回值和CString比较的问题

自己起头化了一个CString对象,CStringb("已审查批准"卡塔尔国;然后在listcontrol列表用GetItemText重返八个CString对象,内容...

详细>>

一步一步学多线程-Timer,多线程-timer

if(g_cdma.ConnectCom(_T("COM"))){HRESULThr;IConnectionPointContainer*pConnectionPointContainer=NULL;IConnectionPoint*pConnectionPoint=NULL;hr=g_cdma.m_...

详细>>