数据库
商品编号 商品名称
001 - 糖
001 糖 ¦
00101 红糖 ¦_ 00101- 红糖
002 酒 ¦ ¦
00201 白酒 ¦ 00102- 白糖
¦
002-酒
¦
¦_00201-白酒
¦
00202- 啤酒
怎么实现这个treeview,能不能搞点代码,谢谢了
商品编号 商品名称
001 - 糖
001 糖 ¦
00101 红糖 ¦_ 00101- 红糖
002 酒 ¦ ¦
00201 白酒 ¦ 00102- 白糖
¦
002-酒
¦
¦_00201-白酒
¦
00202- 啤酒
怎么实现这个treeview,能不能搞点代码,谢谢了
解决方案 »
- CSDN的当官的听着.给我加1000分上.要不然我要写个灌水机刷分了.
- 如何使窗口,在输入一串字符后--------------激活事件?
- 解遍数据的问题?
- 请问手写板为何在开发的应用程序上写不上汉字?在其他字处理软件上能写上。分不多了。
- 有北京的兄弟一起合租房子吗?顺便可以一起讨论技术(Delphi,51单片机,嵌入式ARM Linux)
- 如何让dbgrid1中的一列生成下拉框
- ???
- 请教netusb2401在delphi环境中编程问题
- odbc 問題
- 谁有.dll的登陆数据库的原代码吗?我想参考参考,我自己做的不是不能定位输入点就是内存地址错误?请多关照了。
- 请教动态创建窗口然后释放窗口的内存问题.
- SQL2000触发器的问题
var
RootNode,cfNode,hwNode,xNode:TTreeNode;
i,j,cf,hw:Integer;
begin
hw:=0;
cf:=0;
TreeView1.Color:=RGB($ff,$ff,$e0);
cfNode:=Nil;
hwNode:=Nil; GetHwInfoForTree;//得到hwset[i,J]的值
RootNode:=TreeView1.Items.AddChild(Nil,'粮库1');
RootNode.ImageIndex:=2;
for i:=0 to hwCount-1 do
begin
if cf<>hwset[i,0] then
begin
cf:=hwset[i,0];
cfNode:=TreeView1.Items.AddChild(RootNode,'仓房'+IntToStr(cf));
cfNode.ImageIndex:=1;
end;
if hw<>hwset[i,1] then
begin
hw:=hwset[i,1];
hwNode:=TreeView1.Items.AddChild(cfNode,'货位'+IntToStr(hw));
hwNode.ImageIndex:=3;
end;
for j:=0 to hwset[i,2]-1 do
begin
xNode:=TreeView1.Items.AddChild(hwNode,'测线'+IntToStr(j+1));
xNode.ImageIndex:=4;
end;
end;
TreeView1.Selected:=TreeView1.Items[1]; //默认选中节点
//TreeView1.Items[0].Expand(False);end;
procedure TMainForm.GetHwInfoForTree;
begin
hwCount:=0;
with QGetHwInfo do
begin
close;
SQL.Clear;
SQL.Add('select * from configT order by cf,hw');
Open;
end;
SetLength(hwset,QGetHwInfo.RecordCount);
QGetHwInfo.first;
while not QGetHwInfo.eof do
begin
hwset[hwCount,0]:=QGetHwInfo.FieldByName('cf').AsInteger;
hwset[hwCount,1]:=QGetHwInfo.FieldByName('hw').AsInteger;
hwset[hwCount,2]:=QGetHwInfo.FieldByName('xs').AsInteger;
inc(hwCount);
QGetHwInfo.next;
end;
QGetHwInfo.Close;
end;
type PNodeData = ^NodeData;
NodeData = record
id : integer;
pid : integer;
name : string;
memo : string;
end;//填充树
procedure TfrmStoreBase.fillTree(Sender: TObject);
var nData : PNodeData;
ss : TStringList;
aNode,bNode,pNode : TTreeNode;
i,idx,j : integer;
strSQL : string;
begin
strSQL := ' select * from location where status > 0 ';
DestroyTree(self);
with adoquery2 do
begin
close;
sql.Clear;
sql.Add(strSQL);
open;
first;
ss := TStringList.Create;
for i := 0 to recordcount -1 do
begin
//首先把数据库中的数据取出来构建一个一个数据结构
new(nData);
nData^.id := fieldbyname('locaid').AsInteger;
nData^.pid := fieldbyname('ParentID').AsInteger;
nData^.name := fieldbyname('LocaDesc').AsString;
nData^.memo := fieldbyname('LocaCode').AsString;
//root node
aNode := TreeView1.Items.AddObject(nil,nData.name,nData); ss.AddObject(inttostr(nData.id),aNode);
next;
end;
close;
nData := nil;
end;
//下面的代码的作用是重新排列树结构,使父节点和子节点联系起来
TreeView1.Items.BeginUpdate;
aNode := TreeView1.Items.GetFirstNode;
while( not (aNode = nil) ) do
begin
idx := PNodeData(aNode.Data)^.pid;
i := ss.IndexOf(inttostr(idx));
if i = -1 then
begin
aNode := aNode.getNextSibling;
continue;
end
else
begin
//改变相应的图标
pNode := TTreeNode(ss.Objects[i]);
pNode.ImageIndex := 1;
pNode.SelectedIndex := 1;
bNode := aNode;
bNode.ImageIndex := 0;
bNode.SelectedIndex := 0;
aNode := aNode.getNextSibling;
bNode.MoveTo(pNode,naAddChild);
end;
end;
ss.Destroy;
ss := nil;
end;
//销毁树,主要是销毁自己创建的树节点中的数据结构procedure TfrmStoreBase.DestroyTree(Sender: TObject);
var aNode : TTreeNode;
pNode : PNodeData;
begin
//释放掉所有的DATA aNode := TreeView1.Items.GetFirstNode;
while (aNode <> nil) do
begin
new(PNode);
pNode := PNodeData(aNode.Data);
dispose(pNode);
pNode := nil;
aNode := aNode.GetNext;
end;
aNode := nil;
end;
标题:树型控件treeview与数据库的结合使用作者:delphiun 出处: 更新时间: 2004年03月19日
{前 言
树形图用于显示按照树形结构进行组织的数据,其用途比较广泛,如计算机中的文件系统(Windows95中的资源管理器)、企业或公司的组成结构等。VB、PB、Delphi等工具提供了一个功能很强的树型控件TTreeView,可以用来描述复杂的层次关系。由于树形图结构较复杂,使用起来常不知如何下手。笔者结合电信综合统计管理系统中指标维护这一具体实例,详细阐述在Delphi下如何将树型控件的使用与数据库联系起来,实现数据分任意多层显示,方便地进行增加、修改、删除操作,而且用拖放技术实现各层数据之间的移动、复制。笔者希望通过对该实例的阐述,达到抛砖引玉的效果,与各位同仁相互交流,共同进步。一、指标树的建立具体方法是:创建一个数据库,设计指标表t_pub_index,包含index_id、parent_id、index_name字段,其它字段根据实际业务而定,指标名称index_name将在树型控件的节点上显示,index_id字段保存节点的唯一标识号,parent_id表示当前节点的父节点号,标识号组成了一个“链表”,记录了树上节点的结构。设计一窗体Frm_sys_index,其上放置TreeView控件tv_zb、Query控件Query1及其它指标属性编辑显示控件。一个树的节点又包含文本(Text)和数据(Data)。Text为String类,用来显示指标或指标目录名称。Data则为无定形指针(Untyped Pointer),可以指向一个与节点相联系的数据结构,该结构与数据库指标表相应域关联,如指标ID、上级节点ID。Query控件的表达式为:select index_id, parent_id, index_name from t_pub_indexstart with index_id=0 connect by prior index_id=parent_id其中start with 和connect by 是Oracle的SQL语句的保留字,使一条记录的parent_id列的值等于前一记录的index_id列的值,并以parent_id等于0的记录开始。建树的基本思路是:
}
procedure TCustomerRelationFrm.createtree;
var
curValue: indexPointer; //指向与节点相联系的数据结构的指针
curNode : TTreeNode; //当前节点
curid :STRING; //当前节点标识号begin
curNode := nil;
curid :='-1';
mainfrm.clientdataset2.Open;
mainfrm.clientdataset2.first;
while not mainfrm.clientdataset2.Eof do
begin
new(curValue);
With curValue^ do
//将数据库指标表t_pub_index各字段值赋curValue 所指数据结构
while(curid <> curValue.parent_id) do //当前节点的标识号不等于当前记录的父节点号
begin
curNode:= curNode.parent;
curid:=indexPointer(curNode.data).index_id;
parent_id:=mainfrm.clientdataset2.Fields[1].Value;
index_id:=mainfrm.clientdataset2.Fields[0].Value;
index_name:=mainfrm.clientdataset2.Fields[2].Value;;
end;
curNode := tv_zb.Items.AddChildObject(curNode,curValue^.index_name,curValue); //在当前节点上添加子节点,显示节点指标名称,所带指针指向一个与指标数据相联系的数据结构
curid := indexPointer(curNode.data).index_id;
mainfrm.clientdataset2.next;
end;
mainfrm.clientdataset2.close;
end;//二、增加、删除、修改树节点//单纯在Treeview 上增加、删除、修改节点只需用它本身提供的Treeview.Items. AddChildObject、 Treeview.Selected.Delete、Treeview.Selected.EditText等方法即可,但要相应修改数据库中的数据,必须通过递归调用同一个函数(用于删除一个选项)来遍历所选节点下的所有子节点。下面以删除节点为例介绍具体实现流程:function TCustomerRelationFrm.delnode(node1:TTreenode):TTreenode;varchildnode:TTreenode;beginchildnode:=node1.GetLastChild; //按倒序获得子项,因为删除选项时,列表会发生变化while childnode<>nil dochildnode:=delnode(childnode); //如子项不为空,进行递归调用//index_id:=indexpointer(node1.data).index_id;//获得该节点对应指标//在数据库删除相应指标;result:=node1.parent.GetPrevChild(node1); //定位到该节点的上一节点node1.delete; //删除树节点end;//三、拖动树节点//拖动树节点基本上是通过建立目标项的新子项、向它复制源项、删除原项来移动选项。与上述删除操作相似,也是通过递归调用同一个函数(用于移动一个选项),按倒序移动所选节点下的所有子节点。下面是递归过程的代码:procedure TCustomerRelationFrm.CopyNodeUnder(treeview:TTreeview;sourcenode,targetnode:ttreenode);
var
newnode:ttreenode;
i:integer;
begin
newnode:=treeview.items.addchildfirst(targetnode,''); //建立目标项
newnode.assign(sourcenode); //复制源项属性
for i:=sourcenode.count-1 downto 0 do
BEGIN //递归调用,按倒序移动其所有子项
CopyNodeUnder (treeview,sourcenode.item[i],newnode);
END;
treeview.items.delete(sourcenode); //删除源项
end;//Treeview对拖动操作提供支持,我们将组件的DragKind属性设置为dkDrag,DragMode属性设置为dmAutomatic,并为OnDragOver与OnDragDrop事件编写了处理程序。OnDragOver事件处理程序对允许移动的条件进行判断,排除需要避免的特殊情况。代码如下:procedure TCustomerRelationFrm.tv_zbDragOver(Sender, Source: TObject; X,Y: Integer; State: TDragState; var Accept: Boolean);var targetnode,sourcenode:TTreenode;begintargetnode:=tv_zb.getnodeat(x,y);if (Source=Sender) and (targetnode<>nil) then //保证移动在TreeView上,且目标节点不为空beginAccept:=true; sourcenode:=tv_zb.selected; //以下代码防止用户将一个选项拖到其子项上(它会随着选项一起移动,导致死循环)while (targetnode.parent<>nil) and (targetnode <> sourcenode) do targetnode:=targetnode.parent; if (targetnode = sourcenode) then Accept:=false; end else Accept:=false; end; //OnDragDrop事件处理程序启动前述移动过程CopyNodeUnder,修改数据库数据。此外,在大批量添加数据到Treeview中时最好使用TreeView.Items.BeginUpdate和 TreeView.Items.EndUpdate,这样能加快显示速度。大致流程如下:procedure TCustomerRelationFrm.tv_zbDragDrop(Sender, Source: TObject; X,Y: Integer);vartargetnode,sourcenode:TTreenode;begintargetnode:=tv_zb.getnodeat(x,y); //获得源节点sourcenode:=tv_zb.selected; //获得目标节点//修改数据库中当前节点的父节点号parent_id,使其等目标节点标识号;tv_zb.items.beginupdate; //禁用TreeView重绘操作trycopynodeunder(tv_zb,sourcenode,targetnode); //启动移动过程tv_zb.selected:=targetnode;finallytv_zb.items.endupdate; //重新设置end;end;
你自己看看估计就研究不出来了
要的话加QQ:5895482