delphi 怎么让Combobox上拉菜单时,显示一个树形结构

delphi 怎么让Combobox上拉菜单时,显示一个树形结构,第1张

可以考虑使用ComboboxEx组件或其他第三方控件。

ComboboxEx 组件同 Combobox 类似,但其 item 多了一个 Indent 属性,这个属性设置0 1 2 3 就可以显示出层级分列了。

推荐使用 TMS 控件包里的 TAdvTreeComboBox 控件,使用方便,功能类似于 TreeView + ComboBox:

树形结构在 delphi 里通常使用 TreeView 控件,如果要进行数据查询,通常会与数据库联用,关键点在于数据库的结构,请参阅以下资料:

>

例一

//刷新Tree 1

procedure TMainFormRefTree();

var

Tags:string ;

RootNode0,RootNode1,RootNode2,RootNode3,RootNode4,RootNode5:TtreeNode;

i:integer;

begin

TreeView1ItemsClear;

RootNode0:=TreeView1ItemsAdd(nil,'全部');

RootNode1:=TreeView1ItemsAdd(nil,'资分类');

RootNode2:=TreeView1ItemsAdd(nil,'部门');

RootNode3:=TreeView1ItemsAdd(nil,'情况');

RootNode4:=TreeView1ItemsAdd(nil,'位置');

RootNode5:=TreeView1ItemsAdd(nil,'方式');

TreeView1Items[0]ImageIndex:=11;

TreeView1Items[1]ImageIndex:=54;

TreeView1Items[2]ImageIndex:=54;

TreeView1Items[3]ImageIndex:=54;

TreeView1Items[4]ImageIndex:=54;

TreeView1Items[5]ImageIndex:=54;

RootNode0SelectedIndex:=RootNode0ImageIndex;

RootNode1SelectedIndex:=RootNode1ImageIndex;

RootNode2SelectedIndex:=RootNode2ImageIndex;

RootNode3SelectedIndex:=RootNode3ImageIndex;

RootNode4SelectedIndex:=RootNode4ImageIndex;

RootNode5SelectedIndex:=RootNode5ImageIndex;

//分类

with DataMq1 do

begin

SQLClear;

SQLAdd('Select Name1 from Navtree where tag=''分类'' ');

Open;

while not eof do

begin

TreeView1ItemsAddChild(RootNode1,FieldValues['Name1']);

next;

end;

end;

(此处省略365个字呵呵)

end;

例二

procedure TForm1showtree; //showtree自定义的

var

mynode:ttreenode;

begin

with adoquery1 do

begin

close;

sqlClear;

sqlAdd('select from aa where value = ''1''');

open;

if recordcount <> 0 then

begin

treeview1ItemsAdd(treeview1TopItem,fieldbyname('name')AsString);

end;

end;

with adoquery2 do

begin

close;

sqlClear;

sqlAdd('select from aa where len(name) = 4');

open;

while not eof do

begin

mynode:= treeview1ItemsAddChild(treeview1TopItem,fieldbyname('name')AsString);

with adoquery3 do

begin

close;

sqlClear;

sqlAdd('select from aa where name like '''+ '%'+ mynodeText+ ''' and len(name) = 6');

open;

if recordcount <> 0 then

begin

first;

begin

treeview1ItemsAddChild(mynode,fieldbyname('name')AsString);

next;

end;

end;

end;

next;

end;

end;

end

例三

一、指标树的建立

具体方法是:创建一个数据库,设计指标表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_index

start 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 TFrm_sys_indexcreatetree;

var

curValue: indexPointer; //指向与节点相联系的数据结构的指针

curNode : TTreeNode; //当前节点

curid : integer; //当前节点标识号

begin

curNode := nil;

curid := -1;

Query_indexOpen;

Query_indexfirst;

while not Query_indexEof do

begin

new(curValue);

With curValue^ do

将数据库指标表t_pub_index各字段值赋curValue 所指数据结构

while(curid <> curValueparent_id) do //当前节点的标识号不等于当前记录的父节点号

begin

curNode := curNodeparent;

curid:= indexPointer(curNodedata)index_id;

end;

curNode := tv_zbItemsAddChildObject(curNode,

curValue^index_name,curValue); //在当前节点上添加子节点,显示节点指标名称,所带指针指向一个与指标数据相联系的数据结构

curid := indexPointer(curNodedata)index_id;

Query_indexnext;

end;

Query_indexclose;

end;

二、增加、删除、修改树节点

单纯在Treeview 上增加、删除、修改节点只需用它本身提供的TreeviewItems AddChildObject、 TreeviewSelectedDelete、TreeviewSelectedEditText等方法即可,但要相应修改数据库中的数据,必须通过递归调用同一个函数(用于删除一个选项)来遍历所选节点下的所有子节点。下面以删除节点为例介绍具体实现流程:

function TFrm_sys_indexdelnode(node1:TTreenode):TTreenode;

var

childnode:TTreenode;

begin

childnode:=node1GetLastChild; //按倒序获得子项,因为删除选项时,列表会发生变化

while childnode<>nil do

childnode:=delnode(childnode); //如子项不为空,进行递归调用

index_id:=inttostr(indexpointer(node1data)index_id);//获得该节点对应指标

在数据库删除相应指标;

result:=node1parentGetPrevChild(node1); //定位到该节点的上一节点

node1delete; //删除树节点

end;

三、拖动树节点

拖动树节点基本上是通过建立目标项的新子项、向它复制源项、删除原项来移动选项。与上述删除 *** 作相似,也是通过递归调用同一个函数(用于移动一个选项),按倒序移动所选节点下的所有子节点。下面是递归过程的代码:

procedure TFrm_sys_indexCopyNodeUnder(treeview:TTreeview;

sourcenode,targetnode:ttreenode);

var

newnode:ttreenode;

i:integer;

begin

newnode:=treeviewitemsaddchildfirst(targetnode,''); //建立目标项

newnodeassign(sourcenode); //复制源项属性

for i:=sourcenodecount-1 downto 0 do //递归调用,按倒序移动其所有子项

CopyNodeUnder (treeview,sourcenodeitem[i],newnode);

treeviewitemsdelete(sourcenode); //删除源项

end;

Treeview对拖动 *** 作提供支持,我们将组件的DragKind属性设置为dkDrag,DragMode属性设置为dmAutomatic,并为OnDragOver与OnDragDrop事件编写了处理程序。OnDragOver事件处理程序对允许移动的条件进行判断,排除需要避免的特殊情况。代码如下:

procedure TFrm_sys_indextv_zbDragOver(Sender, Source: TObject; X,

Y: Integer; State: TDragState; var Accept: Boolean);

var

targetnode,sourcenode:TTreenode;

begin

targetnode:=tv_zbgetnodeat(x,y);

if (Source=Sender) and (targetnode<>nil) then //保证移动在TreeView上,且目标节点不为空

begin

Accept:=true;

sourcenode:=tv_zbselected;

//以下代码防止用户将一个选项拖到其子项上(它会随着选项一起移动,导致死循环)

while (targetnodeparent<>nil) and (targetnode <> sourcenode) do

targetnode:=targetnodeparent;

if (targetnode = sourcenode) then Accept:=false;

end

else Accept:=false;

end;

OnDragDrop事件处理程序启动前述移动过程CopyNodeUnder,修改数据库数据。此外,在大批量添加数据到Treeview中时最好使用TreeViewItemsBeginUpdate和 TreeViewItemsEndUpdate,这样能加快显示速度。大致流程如下:

procedure TFrm_sys_indextv_zbDragDrop(Sender, Source: TObject; X,

Y: Integer);

var

targetnode,sourcenode:TTreenode;

begin

targetnode:=tv_zbgetnodeat(x,y); //获得源节点

sourcenode:=tv_zbselected; //获得目标节点

修改数据库中当前节点的父节点号parent_id,使其等目标节点标识号;

tv_zbitemsbeginupdate; //禁用TreeView重绘 *** 作

try

copynodeunder(tv_zb,sourcenode,targetnode); //启动移动过程

tv_zbselected:=targetnode;

finally

tv_zbitemsendupdate; //重新设置

end;

end;

例四

给你一段超级短的代码,caption字段就是你的value字段,因value是保留字,所以我改成这个了。

procedure TForm1Button1Click(Sender: TObject);

var

ss: TStrings;

begin

AdoQuery1SQLText := 'SELECT name,caption FROM test8 ORDER BY name';

AdoQuery1Open;

ss := TStringListCreate;

while not AdoQuery1Eof do

begin

ssAdd(StringOfChar(#9,(Length(Trim(AdoQuery1FieldValues['name'])) div 2)-1)

+ AdoQuery1FieldValues['caption']);

AdoQuery1Next;

end;

ShowMessage(ssText);

ssSaveToFile('d:\test8txt');

ssFree;

TreeView1LoadFromFile('d:\test8txt');

end;

纯粹在百度搜索的,你参考一下吧:

实现TreeView结点拖拽的实例

下面的程序片段演示了如何实现拖拽treeview构件结点的例子

{鼠标按下时执行的语句}

procedure TForm1Treeview1MouseDown(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

{判断左键按下并且鼠标点在一个结点上开始实现拖拽}

if ( Button = mbLeft ) and

( htOnItem in Treeview1GetHitTestInfoAt( X, Y ) ) then

begin

Treeview1BeginDrag( False );

end;

end;

{鼠标拖动执行语句}

procedure TForm1Treeview1DragOver( Sender, Source: TObject;

X, Y: Integer; State: TDragState; var Accept: Boolean);

var

Node : TTreeNode;

begin

if Source = Treeview1 then

begin

Node := Treeview1GetNodeAt( X, Y ); {取当前结点}

if Node <> nil then {当前结点不为空才能实现拖拽,accept:=true}

Accept := true;

end;

end;

{鼠标释放时执行的语句}

procedure TForm1Treeview1DragDrop( Sender, Source: TObject;

X, Y : Integer );

var

TempNode : TTreeNode;

AttachMode : TNodeAttachMode;

begin

if Treeview1Selected = nil then

Exit;

AttachMode := naAddChild; {设置结点移动模式,设移动结点为子结点}

{ 注意在这里存在一个bug,当移动结点时,如果目标结点没有子结点,}

{ 则加入的新的子结点会失败,所以先在当前目标结点的下面 }

{ 加入一个临时子结点,移动完毕后,再将临时结点删除 }

Treeview1ItemsBeginUpdate;

try

TempNode := Treeview1ItemsAddChild( Treeview1DropTarget,

'Temp' );

try

{ 移动选中的结点到目标结点 }

Treeview1SelectedMoveTo( Treeview1DropTarget, AttachMode );

finally

TempNodeFree; { 不要忘了释放临时结点 }

end;

finally

Treeview1ItemsEndUpdate;

end;

end;

以上就是关于delphi 怎么让Combobox上拉菜单时,显示一个树形结构全部的内容,包括:delphi 怎么让Combobox上拉菜单时,显示一个树形结构、如何从数据库中查出数据在delphi 中的树展示、delphi中treeview的用法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9749811.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存