ID NAME DEPPID
1 XX -1 -----根结点(唯一)
2 YY 0 -----为DEPID为-1的子结点
3 ZZ 0 -----为DEPID为-1的子结点
4 TT 2
5 SS 2 ----表示为父节点ID为2
6 QQ 2 ----表示为父节点ID为2
7 RR 3 ----表示为父节点ID为3
.. ... ....
怎样使树为:
XX
YY
TT
SS
ZZ
RR 这种树型 表中的根结只有一个,根结点的子节的DEPPID为0,,DEPPID为0的相应子节是其DEPPID为其相应的ID。是用什么算法作比较好,FOR或递归,,给个具体的代码;
19 个解决方案
#1
将数据select出来时order by DEPPID,确保各个节点的顺序。即父节点要先被添加到TreeView中。
然后顺序的逐层添加,DEPPID可以保存到TreeItem的Data属性中,方便后续处理,或重新入库。
然后顺序的逐层添加,DEPPID可以保存到TreeItem的Data属性中,方便后续处理,或重新入库。
#2
不是TreeItem,应该是TreeNode,不好意思。
#3
帮顶
#4
select * from table order by DEPPID;
以下是實現的代碼:
TStringList *sg_id = new TStringList;
TStringList *sg_deppid = new TStringList;
sg_id->Add("1=XX");
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
以下是實現的代碼:
TStringList *sg_id = new TStringList;
TStringList *sg_deppid = new TStringList;
sg_id->Add("1=XX");
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
#5
/*
如果数据很多的话,而且也不知道总共有多少子层次的话
最好先只显示第1,2层的节点,(或者只显示第1层的节点)
(按你的实际情况应该是查询deppid==-1)就是第1层节点
当用户点击某层的节点时,再将这层节点的孩子节点数据从数据库读取出来,
添加到当前节点下面。这样由用户的点击来读取数据。(像Windows注册表就适合这种)
如果只是有限的数据,层数也知道,那么你可以先把所有的数据读取出来,然后根据DepID
来决定他们到底如何显示。
*/
void __fastcall TForm1::InitialTreeView(TTreeView *pTreeView,TADOConnection *pADOConnection)
{
int uid ;
AnsiString uname;
TTreeNode *node,*root;
TTreeNode *tempNode =0;
root=node =0;
if(!pADOConnection||!pADOConnection->Connected)
{
MessageBox(0,"数据库发生错误或未连接!","提示信息",MB_OK|MB_ICONWARNING);
return ;
}
TADOQuery *ptrQuery =0;
ptrQuery =new TADOQuery(this);
ptrQuery->Connection= pADOConnection;
AnsiString strSQL="select * from University";
ptrQuery->SQL->Add(strSQL);
ptrQuery->Open();
if(ptrQuery->RecordCount>0)
{
uid = ptrQuery->FieldByName("UniversityID")->AsInteger;
uname= ptrQuery->FieldByName("UniversityName")->AsString;
root = pTreeView->Items->AddChild(0,uname);
root->Data=(TObject*)uid;
root->ImageIndex =1 ;
root->SelectedIndex =root->ImageIndex ;
}
else
{
MessageBox(0,"没有找到学校的数据","警告",MB_OK|MB_ICONWARNING);
return ;
}
strSQL= "select AcademyID,AcademyName from Academy where UniversityID=:uid"; //学校下面的二级学院
int cid;
AnsiString cname;
ptrQuery->Close();
ptrQuery->SQL->Clear();
ptrQuery->SQL->Add(strSQL);
ptrQuery->Parameters->ParamByName("uid")->Value=uid;
ptrQuery->Open();
while(!ptrQuery->Eof)
{
cid = ptrQuery->FieldByName("AcademyID")->AsInteger;
cname= ptrQuery->FieldByName("AcademyName")->AsString;
node =pTreeView->Items->AddChild(root,cname);
node->Data =(TObject*)cid;
node->ImageIndex = 2;
node->SelectedIndex =node->ImageIndex ;
tempNode = pTreeView->Items->AddChild(node,"#***#");//供显示用
tempNode->Data = (TObject*)(-1);
ptrQuery->Next();
}
ptrQuery->Close();
}
void __fastcall TForm1::TVExpanding(TObject *Sender, TTreeNode *Node,
bool &AllowExpansion)
{
switch( Node->Level)
{
case 1://二级学院节点
if(Node->Count==1&& Node->getFirstChild() &&
Node->getFirstChild()->Text=="#***#")
{
DeleteTempNode(Node);
AddDepartment(Node);
}
break;
//其他case语句略
default: break ;
}
}
//添加二级学院下面的系节点,就相当于你的deppid = 1的节点
void __fastcall TForm1::AddDepartment(TTreeNode *ParentNode)
{
TTreeNode *root =0;
int uid=-1;
int aid= -1;
root =ParentNode->Parent;
if(root==0)
return ;
uid=(int)root->Data;
aid=(int)ParentNode->Data ;
AnsiString strSQL="select DepartmentID, DepartmentName from Department ";
strSQL +="where AcademyID=:aid and UniversityID=:uid ";
if(TVQuery->Active)
TVQuery->Close();
TVQuery->SQL->Clear();
TVQuery->SQL->Add(strSQL);
TVQuery->Parameters->ParamByName("aid")->Value=aid;
TVQuery->Parameters->ParamByName("uid")->Value=uid;
TVQuery->Open();
int did ;
AnsiString dname;
TTreeNode *childNode=0;
TTreeNode *childchildNode=0;
while(!TVQuery->Eof)
{
did = TVQuery->FieldByName("DepartmentID")->AsInteger;
dname =TVQuery->FieldByName("DepartmentName")->AsString;
childNode =TV->Items->AddChild(ParentNode,dname);
childNode->Data=(TObject*)did;
childNode->ImageIndex =3;
childNode->SelectedIndex = childNode->ImageIndex ;
childchildNode= TV->Items->AddChild(childNode,"#***#");
childchildNode->Data= (TObject*)(-1);
TVQuery->Next();
}
}
//删除临时节点
void __fastcall TForm1::DeleteTempNode(TTreeNode *tmpNode)
{
TTreeNode *childNode =tmpNode->getFirstChild();
if(childNode!=0 && childNode->Text=="#***#")
{
childNode->Delete();
}
}
/*
代码不方便都贴出来,只是为了说明这种层次的节点,用TreeView还是很方便的,
上面的代码就是先显示学校节点(depid=-1) 和 学校下面的二级学院节点(depid=0),
当用户点击树的第1层节点(depid=0),就是二级学院节点时,就将这个二级学院
拥有所有系的节点(depid=1)全部显示出来
*/
#6
要是很多数据时,不是要写死了啊...
#7
你那种方式是有点相象,,但我说有情况不是完全跟你一样的,数据量到底多少是不知道的啊. 我的树表示有两种类型.
#8
我只是擧例說先把數據整理好 不是說要一個一個寫
你整理數據可以用
ADOQuery去執行String strSql = "select * from table order by DEPPID";
然後循環結果集
if(!ADOQuery1->Eof)
{
String str = ADOQuery1->FieldByName("ID")->AsString;
str += "=" + ADOQuery1->FieldByName("Name")->AsString;
sg_id->Add(str);
}
這樣不就可以了 不用去一個一個寫 都用代碼實現
#9
我觉得把
2 YY 0 -----为DEPID为-1的子结点
3 ZZ 0 -----为DEPID为-1的子结点
改成
2 YY 1 -----表示为父节点ID为1
3 ZZ 1 -----表示为父节点ID为1
比较合理,同一个域里数值的涵义尽量一致
2 YY 0 -----为DEPID为-1的子结点
3 ZZ 0 -----为DEPID为-1的子结点
改成
2 YY 1 -----表示为父节点ID为1
3 ZZ 1 -----表示为父节点ID为1
比较合理,同一个域里数值的涵义尽量一致
#10
到现在也没想出什么好办法啊。帮帮,谁能实现并运行成功,马上给100---分
#11
不可能把代碼完全寫出來的
實現部分的代碼就是下面的
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
剩下其實已經沒有什麽工作量了,就是把sg_id和sg_deppid中的數據填進去,而且也不是一條一條的寫,在select出來之後去循環結果集合然後去填數據就可以了
實現部分的代碼就是下面的
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
剩下其實已經沒有什麽工作量了,就是把sg_id和sg_deppid中的數據填進去,而且也不是一條一條的寫,在select出來之後去循環結果集合然後去填數據就可以了
#12
楼上的.你这样写,你的根结点变成了子节点了啊. 这里的AddChild用得不对吧...
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
有时间帮我写了整的,,自己测试一下,,,;;说明一下方法..
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
有时间帮我写了整的,,自己测试一下,,,;;说明一下方法..
#13
你開一個新的Appication
在Form上就放一個TreeView
一個button
然後再button的click事件裏把下面的代碼複製進取,然後運行
TStringList *sg_id = new TStringList;
TStringList *sg_deppid = new TStringList;
sg_id->Add("1=XX");
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
你看看是你要的效果不
在Form上就放一個TreeView
一個button
然後再button的click事件裏把下面的代碼複製進取,然後運行
TStringList *sg_id = new TStringList;
TStringList *sg_deppid = new TStringList;
sg_id->Add("1=XX");
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
你看看是你要的效果不
#14
對了 treeview的name改成TV 程序可以直接跑 我這裡測試沒有問題
#15
AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
第一個參數是父節點 我這裡用的是NULL 所以這個時候節點就是根節點
第一個參數是父節點 我這裡用的是NULL 所以這個時候節點就是根節點
#16
sg_id->Add("1=XX");
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
要是数据很多的时候,要是表数据很多时,你怎么办啊.
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
要是数据很多的时候,要是表数据很多时,你怎么办啊.
#17
這個只是給你個例子 讓你把程序跑起來
數據多當然不可能一個一個這麽寫
直接用ADQQuery去讀數據庫 然後循環結果集 把數據填到兩個TStringList裏面
然後循環結果集
ADOQuery1->Close(); //自行添加ADOConnention,并配置
ADOQuery1->SQL->Clear();
ADOQuery1->SQL->Add("select * from table order by DEPPID");
ADOQuery1->Open();
if(!ADOQuery1->Eof)
{
String str = ADOQuery1->FieldByName("ID")->AsString;
str += "=" + ADOQuery1->FieldByName("Name")->AsString;
sg_id->Add(str);
String str2 = ADOQuery1->FieldByName("ID")->AsString;
str2 += "=" + ADOQuery1->FieldByName("sg_deppid")->AsString;
sg_deppid->Add(str2);
ADOQuery1->Next();
}
這樣就可以把值都填到兩個TStringList裏了
不用一個一個去寫,我那麽寫只是想讓程序跑起來 讓你看看效果
數據多當然不可能一個一個這麽寫
直接用ADQQuery去讀數據庫 然後循環結果集 把數據填到兩個TStringList裏面
然後循環結果集
ADOQuery1->Close(); //自行添加ADOConnention,并配置
ADOQuery1->SQL->Clear();
ADOQuery1->SQL->Add("select * from table order by DEPPID");
ADOQuery1->Open();
if(!ADOQuery1->Eof)
{
String str = ADOQuery1->FieldByName("ID")->AsString;
str += "=" + ADOQuery1->FieldByName("Name")->AsString;
sg_id->Add(str);
String str2 = ADOQuery1->FieldByName("ID")->AsString;
str2 += "=" + ADOQuery1->FieldByName("sg_deppid")->AsString;
sg_deppid->Add(str2);
ADOQuery1->Next();
}
這樣就可以把值都填到兩個TStringList裏了
不用一個一個去寫,我那麽寫只是想讓程序跑起來 讓你看看效果
#18
node_parent =tv->Items->AddChild(NUll,sg_id->Values[sg_id->Names[i]].Trim()); 这种的过不去.类型不同吧..
#19
以前用Delphi写过,现在不记得了。
#20
#1
将数据select出来时order by DEPPID,确保各个节点的顺序。即父节点要先被添加到TreeView中。
然后顺序的逐层添加,DEPPID可以保存到TreeItem的Data属性中,方便后续处理,或重新入库。
然后顺序的逐层添加,DEPPID可以保存到TreeItem的Data属性中,方便后续处理,或重新入库。
#2
不是TreeItem,应该是TreeNode,不好意思。
#3
帮顶
#4
select * from table order by DEPPID;
以下是實現的代碼:
TStringList *sg_id = new TStringList;
TStringList *sg_deppid = new TStringList;
sg_id->Add("1=XX");
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
以下是實現的代碼:
TStringList *sg_id = new TStringList;
TStringList *sg_deppid = new TStringList;
sg_id->Add("1=XX");
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
#5
/*
如果数据很多的话,而且也不知道总共有多少子层次的话
最好先只显示第1,2层的节点,(或者只显示第1层的节点)
(按你的实际情况应该是查询deppid==-1)就是第1层节点
当用户点击某层的节点时,再将这层节点的孩子节点数据从数据库读取出来,
添加到当前节点下面。这样由用户的点击来读取数据。(像Windows注册表就适合这种)
如果只是有限的数据,层数也知道,那么你可以先把所有的数据读取出来,然后根据DepID
来决定他们到底如何显示。
*/
void __fastcall TForm1::InitialTreeView(TTreeView *pTreeView,TADOConnection *pADOConnection)
{
int uid ;
AnsiString uname;
TTreeNode *node,*root;
TTreeNode *tempNode =0;
root=node =0;
if(!pADOConnection||!pADOConnection->Connected)
{
MessageBox(0,"数据库发生错误或未连接!","提示信息",MB_OK|MB_ICONWARNING);
return ;
}
TADOQuery *ptrQuery =0;
ptrQuery =new TADOQuery(this);
ptrQuery->Connection= pADOConnection;
AnsiString strSQL="select * from University";
ptrQuery->SQL->Add(strSQL);
ptrQuery->Open();
if(ptrQuery->RecordCount>0)
{
uid = ptrQuery->FieldByName("UniversityID")->AsInteger;
uname= ptrQuery->FieldByName("UniversityName")->AsString;
root = pTreeView->Items->AddChild(0,uname);
root->Data=(TObject*)uid;
root->ImageIndex =1 ;
root->SelectedIndex =root->ImageIndex ;
}
else
{
MessageBox(0,"没有找到学校的数据","警告",MB_OK|MB_ICONWARNING);
return ;
}
strSQL= "select AcademyID,AcademyName from Academy where UniversityID=:uid"; //学校下面的二级学院
int cid;
AnsiString cname;
ptrQuery->Close();
ptrQuery->SQL->Clear();
ptrQuery->SQL->Add(strSQL);
ptrQuery->Parameters->ParamByName("uid")->Value=uid;
ptrQuery->Open();
while(!ptrQuery->Eof)
{
cid = ptrQuery->FieldByName("AcademyID")->AsInteger;
cname= ptrQuery->FieldByName("AcademyName")->AsString;
node =pTreeView->Items->AddChild(root,cname);
node->Data =(TObject*)cid;
node->ImageIndex = 2;
node->SelectedIndex =node->ImageIndex ;
tempNode = pTreeView->Items->AddChild(node,"#***#");//供显示用
tempNode->Data = (TObject*)(-1);
ptrQuery->Next();
}
ptrQuery->Close();
}
void __fastcall TForm1::TVExpanding(TObject *Sender, TTreeNode *Node,
bool &AllowExpansion)
{
switch( Node->Level)
{
case 1://二级学院节点
if(Node->Count==1&& Node->getFirstChild() &&
Node->getFirstChild()->Text=="#***#")
{
DeleteTempNode(Node);
AddDepartment(Node);
}
break;
//其他case语句略
default: break ;
}
}
//添加二级学院下面的系节点,就相当于你的deppid = 1的节点
void __fastcall TForm1::AddDepartment(TTreeNode *ParentNode)
{
TTreeNode *root =0;
int uid=-1;
int aid= -1;
root =ParentNode->Parent;
if(root==0)
return ;
uid=(int)root->Data;
aid=(int)ParentNode->Data ;
AnsiString strSQL="select DepartmentID, DepartmentName from Department ";
strSQL +="where AcademyID=:aid and UniversityID=:uid ";
if(TVQuery->Active)
TVQuery->Close();
TVQuery->SQL->Clear();
TVQuery->SQL->Add(strSQL);
TVQuery->Parameters->ParamByName("aid")->Value=aid;
TVQuery->Parameters->ParamByName("uid")->Value=uid;
TVQuery->Open();
int did ;
AnsiString dname;
TTreeNode *childNode=0;
TTreeNode *childchildNode=0;
while(!TVQuery->Eof)
{
did = TVQuery->FieldByName("DepartmentID")->AsInteger;
dname =TVQuery->FieldByName("DepartmentName")->AsString;
childNode =TV->Items->AddChild(ParentNode,dname);
childNode->Data=(TObject*)did;
childNode->ImageIndex =3;
childNode->SelectedIndex = childNode->ImageIndex ;
childchildNode= TV->Items->AddChild(childNode,"#***#");
childchildNode->Data= (TObject*)(-1);
TVQuery->Next();
}
}
//删除临时节点
void __fastcall TForm1::DeleteTempNode(TTreeNode *tmpNode)
{
TTreeNode *childNode =tmpNode->getFirstChild();
if(childNode!=0 && childNode->Text=="#***#")
{
childNode->Delete();
}
}
/*
代码不方便都贴出来,只是为了说明这种层次的节点,用TreeView还是很方便的,
上面的代码就是先显示学校节点(depid=-1) 和 学校下面的二级学院节点(depid=0),
当用户点击树的第1层节点(depid=0),就是二级学院节点时,就将这个二级学院
拥有所有系的节点(depid=1)全部显示出来
*/
#6
要是很多数据时,不是要写死了啊...
#7
你那种方式是有点相象,,但我说有情况不是完全跟你一样的,数据量到底多少是不知道的啊. 我的树表示有两种类型.
#8
我只是擧例說先把數據整理好 不是說要一個一個寫
你整理數據可以用
ADOQuery去執行String strSql = "select * from table order by DEPPID";
然後循環結果集
if(!ADOQuery1->Eof)
{
String str = ADOQuery1->FieldByName("ID")->AsString;
str += "=" + ADOQuery1->FieldByName("Name")->AsString;
sg_id->Add(str);
}
這樣不就可以了 不用去一個一個寫 都用代碼實現
#9
我觉得把
2 YY 0 -----为DEPID为-1的子结点
3 ZZ 0 -----为DEPID为-1的子结点
改成
2 YY 1 -----表示为父节点ID为1
3 ZZ 1 -----表示为父节点ID为1
比较合理,同一个域里数值的涵义尽量一致
2 YY 0 -----为DEPID为-1的子结点
3 ZZ 0 -----为DEPID为-1的子结点
改成
2 YY 1 -----表示为父节点ID为1
3 ZZ 1 -----表示为父节点ID为1
比较合理,同一个域里数值的涵义尽量一致
#10
到现在也没想出什么好办法啊。帮帮,谁能实现并运行成功,马上给100---分
#11
不可能把代碼完全寫出來的
實現部分的代碼就是下面的
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
剩下其實已經沒有什麽工作量了,就是把sg_id和sg_deppid中的數據填進去,而且也不是一條一條的寫,在select出來之後去循環結果集合然後去填數據就可以了
實現部分的代碼就是下面的
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
剩下其實已經沒有什麽工作量了,就是把sg_id和sg_deppid中的數據填進去,而且也不是一條一條的寫,在select出來之後去循環結果集合然後去填數據就可以了
#12
楼上的.你这样写,你的根结点变成了子节点了啊. 这里的AddChild用得不对吧...
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
有时间帮我写了整的,,自己测试一下,,,;;说明一下方法..
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
有时间帮我写了整的,,自己测试一下,,,;;说明一下方法..
#13
你開一個新的Appication
在Form上就放一個TreeView
一個button
然後再button的click事件裏把下面的代碼複製進取,然後運行
TStringList *sg_id = new TStringList;
TStringList *sg_deppid = new TStringList;
sg_id->Add("1=XX");
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
你看看是你要的效果不
在Form上就放一個TreeView
一個button
然後再button的click事件裏把下面的代碼複製進取,然後運行
TStringList *sg_id = new TStringList;
TStringList *sg_deppid = new TStringList;
sg_id->Add("1=XX");
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
TTreeNode *node_parent;
for(int i = 0; i < sg_deppid->Count; i++)
{
String strDeppid = sg_deppid->Values[sg_deppid->Names[i]].Trim();
if(strDeppid == "-1")
{
node_parent = TV->Items->AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
}
else if(strDeppid == "0")
{
TTreeNode *node = TV->Items->AddChild(node_parent,sg_id->Values[sg_id->Names[i]].Trim());
}
else
{
String strParent = sg_id->Values[strDeppid].Trim();
for(int j = 0; j < TV->Items->Count; j++)
{
TTreeNode *node = TV->Items->Item[j];
if(node->Text.Trim() == strParent)
TTreeNode *child_node = TV->Items->AddChild(node,sg_id->Values[sg_id->Names[i]].Trim());
}
}
}
delete sg_id;
delete sg_deppid;
你看看是你要的效果不
#14
對了 treeview的name改成TV 程序可以直接跑 我這裡測試沒有問題
#15
AddChild(NULL,sg_id->Values[sg_id->Names[i]].Trim());
第一個參數是父節點 我這裡用的是NULL 所以這個時候節點就是根節點
第一個參數是父節點 我這裡用的是NULL 所以這個時候節點就是根節點
#16
sg_id->Add("1=XX");
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
要是数据很多的时候,要是表数据很多时,你怎么办啊.
sg_id->Add("2=YY");
sg_id->Add("3=ZZ");
sg_id->Add("4=TT");
sg_id->Add("5=SS");
sg_id->Add("6=QQ");
sg_id->Add("7=RR");
sg_deppid->Add("1=-1");
sg_deppid->Add("2=0");
sg_deppid->Add("3=0");
sg_deppid->Add("4=2");
sg_deppid->Add("5=2");
sg_deppid->Add("6=2");
sg_deppid->Add("7=3"); //整理數據 將查詢出來的内容放到兩個TStringList裏
要是数据很多的时候,要是表数据很多时,你怎么办啊.
#17
這個只是給你個例子 讓你把程序跑起來
數據多當然不可能一個一個這麽寫
直接用ADQQuery去讀數據庫 然後循環結果集 把數據填到兩個TStringList裏面
然後循環結果集
ADOQuery1->Close(); //自行添加ADOConnention,并配置
ADOQuery1->SQL->Clear();
ADOQuery1->SQL->Add("select * from table order by DEPPID");
ADOQuery1->Open();
if(!ADOQuery1->Eof)
{
String str = ADOQuery1->FieldByName("ID")->AsString;
str += "=" + ADOQuery1->FieldByName("Name")->AsString;
sg_id->Add(str);
String str2 = ADOQuery1->FieldByName("ID")->AsString;
str2 += "=" + ADOQuery1->FieldByName("sg_deppid")->AsString;
sg_deppid->Add(str2);
ADOQuery1->Next();
}
這樣就可以把值都填到兩個TStringList裏了
不用一個一個去寫,我那麽寫只是想讓程序跑起來 讓你看看效果
數據多當然不可能一個一個這麽寫
直接用ADQQuery去讀數據庫 然後循環結果集 把數據填到兩個TStringList裏面
然後循環結果集
ADOQuery1->Close(); //自行添加ADOConnention,并配置
ADOQuery1->SQL->Clear();
ADOQuery1->SQL->Add("select * from table order by DEPPID");
ADOQuery1->Open();
if(!ADOQuery1->Eof)
{
String str = ADOQuery1->FieldByName("ID")->AsString;
str += "=" + ADOQuery1->FieldByName("Name")->AsString;
sg_id->Add(str);
String str2 = ADOQuery1->FieldByName("ID")->AsString;
str2 += "=" + ADOQuery1->FieldByName("sg_deppid")->AsString;
sg_deppid->Add(str2);
ADOQuery1->Next();
}
這樣就可以把值都填到兩個TStringList裏了
不用一個一個去寫,我那麽寫只是想讓程序跑起來 讓你看看效果
#18
node_parent =tv->Items->AddChild(NUll,sg_id->Values[sg_id->Names[i]].Trim()); 这种的过不去.类型不同吧..
#19
以前用Delphi写过,现在不记得了。