我正在用TTreeView
绘制一棵树来模拟一棵矩形树。这种树在体育比赛中用于类似支架学的科学。
TTreeView
有一些内置工具,可以更轻松地创建和显示。我实际上需要使用矩形树格式。我使用TTreeView
几乎无法使用它。它仍然在旧根上有错误,它必须成为一个分支,而新根将分成2个分支。
新根目录下的儿童将保持不变。父级和兄弟级必须位于根的另一个分支上。孩子们将保持不变。祖父母及以上将成为父母的子女,直到它击中旧的根,它将再次穿过孩子。
我无法确定旧根的位置,并且经常再次添加不需要的额外节点。 CreateDownNode
遍历树。 CreateUpNode
遍历树。
以下是一些代码:
procedure TfrmTreeListDown.btnSetRootClick(Sender: TObject);
var
SelectedTreeMember,
TreeMember: PTreeViewMember;
dblBrnchLngth,
dblLngth: double;
intNP: integer;
strSlctText,
strNewRootParent,
strTopLabel: string;
NdRoot,
NCT,
NCB,
NPT,
NSB,
NdTree,
NdTreeBottom,
NdTreeTop: TTreeNode;
begin
if (trvwTextDownBased.Selected = nil) then
exit;
trvwTextDownBased.Selected;
trvwRerootedTree.Items.Clear;
NdRoot := nil;
with TestTableForSpeciesData do
begin
intOldRoot[0] := NodeCount - 1;
intOldRoot[1] := NodeCount;
intOldRoot[2] := NodeCount + 1;
end;
if trvwTextDownBased.Selected.Parent <> nil then
begin
strTopLabel := trvwTextDownBased.Items[0].Text;
strSlctText := trvwTextDownBased.Selected.Text;
SelectedTreeMember := PTreeViewMember(trvwTextDownBased.Selected.Data);
intNP := SelectedTreeMember^.intNodePos;
strNewRootParent := trvwTextDownBased.Selected.Parent.Text;
if intNP in [intOldRoot[0], intOldRoot[1], intOldRoot[2]] then
begin
NdTree := trvwRerootedTree.Items.AddFirst(NdRoot, '*New Root*' + strTopLabel);
TreeMember := PTreeViewMember(trvwTextDownBased.Selected.Data);
NdTreeBottom := trvwRerootedTree.Items.AddChild(NdTree, strBranchLabel(TreeMember^.intNodePos, 0));
end
else
begin
NdTree := trvwRerootedTree.Items.AddFirst(NdRoot, '*New Root*' + trvwTextDownBased.Selected.Text);
TreeMember := PTreeViewMember(trvwTextDownBased.Selected.Data);
dblBrnchLngth := TestTableForSpeciesData.Species[TreeMember^.intNodePos].BranchLength;
dblLngth := dblSplitLength(dblBrnchLngth);
NdTreeBottom := trvwRerootedTree.Items.AddChild(NdTree, strBranchLabel(TreeMember^.intNodePos, dblLngth));
end;
If trvwTextDownBased.Selected.HasChildren then
begin
CreateDownNode(trvwTextDownBased.Selected, NdTreeBottom, kboolFirst);
CreateDownNode(trvwTextDownBased.Selected, NdTreeBottom, kboolSecond);
end;
if trvwTextDownBased.Selected.Parent.Text = strTopLabel then
if trvwTextDownBased.Selected.GetNextSibling = nil then
NdTreeTop := trvwRerootedTree.Items.AddChildFirst(NdTree, trvwTextDownBased.Selected.GetPrevSibling.Text)
else
NdTreeTop := trvwRerootedTree.Items.AddChildFirst(NdTree, trvwTextDownBased.Selected.GetNextSibling.Text)
else
NdTreeTop := trvwRerootedTree.Items.AddChildFirst(NdTree, strBranchLabel(-1, dblBrnchLngth - dblLngth));
if trvwTextDownBased.Selected.Parent.HasChildren then
if trvwTextDownBased.Selected.Parent.GetFirstChild.Text <> trvwTextDownBased.Selected.Text then
begin
CreateDownNode(trvwTextDownBased.Selected.Parent.GetFirstChild, NdTreeTop, kboolFirst);
CreateDownNode(trvwTextDownBased.Selected.Parent.GetFirstChild, NdTreeTop, kboolSecond);
end
else
begin
CreateDownNode(trvwTextDownBased.Selected.Parent.GetLastChild, NdTreeTop, kboolFirst);
CreateDownNode(trvwTextDownBased.Selected.Parent.GetLastChild, NdTreeTop, kboolSecond);
end;
if trvwTextDownBased.Selected.Parent.Text <> trvwTextDownBased.Items[0].Text then
CreateUpNode(trvwTextDownBased.Selected.Parent, NdTreeTop{, NdTreeBottomNSB});
if trvwTextDownBased.Items.Count <> trvwRerootedTree.Items.Count then
MessageDlg('Original Tree:' + IntToStr(trvwTextDownBased.Items.Count) + ' does not equal Rerooted Tree:' + IntToStr(trvwRerootedTree.Items.Count), mtWarning, [mbOK], 0);
end;
if trvwTextDownBased.Selected = nil then
trvwRerootedTree.FullExpand;
end;
procedure TfrmTreeListDown.CreateDownNode(const tnOriginal, tnCurrent: TTreeNode; const boolFirstChild: boolean);
var
tnChild: TTreeNode;
begin
with trvwRerootedTree do
if tnOriginal.HasChildren then
begin
if boolFirstChild then
begin
tnChild := Items.AddChildFirst(tnCurrent, tnOriginal.GetFirstChild.Text);
CreateDownNode(tnOriginal.GetFirstChild, tnChild, kboolFirst);
CreateDownNode(tnOriginal.GetFirstChild, tnChild, kboolSecond);
end
else
begin
tnChild := Items.AddChild(tnCurrent, tnOriginal.GetLastChild.Text);
CreateDownNode(tnOriginal.GetLastChild, tnChild, kboolFirst);
CreateDownNode(tnOriginal.GetLastChild, tnChild, kboolSecond);
end;
end
end;
procedure TfrmTreeListDown.CreateUpNode(const tnOriginal, tnCurrent: TTreeNode);
var
PrntTreeMember: PTreeViewMember;
tnSibling,
tnParent: TTreeNode;
intNP: integer;
begin
with trvwRerootedTree do
begin
if tnOriginal <> nil then
begin
if tnOriginal.Parent.GetFirstChild.Text <> tnCurrent.Text then
begin
tnSibling := Items.AddChildFirst(tnCurrent, tnOriginal.Parent.GetFirstChild.Text);
CreateDownNode(tnOriginal.Parent.GetFirstChild, tnSibling, kboolFirst);
CreateDownNode(tnOriginal.Parent.GetFirstChild, tnSibling, kboolSecond);
end
else
begin
tnSibling := Items.AddChildFirst(tnCurrent, tnOriginal.Parent.GetLastChild.Text);
CreateDownNode(tnOriginal.Parent.GetLastChild, tnSibling, kboolFirst);
CreateDownNode(tnOriginal.Parent.GetLastChild, tnSibling, kboolSecond);
end;
if tnOriginal.Parent <> nil then
if tnOriginal.Parent.Text <> trvwTextDownBased.Items[0].Text then
begin
PrntTreeMember := PTreeViewMember(tnOriginal.Parent.Data);
intNP := PrntTreeMember^.intNodePos;
if intNP in [intOldRoot[0], intOldRoot[1], intOldRoot[2]] then
tnParent := Items.AddChildFirst(tnCurrent, strBranchLabel(-1, TestTableForSpeciesData.Species[TestTableForSpeciesData.NodeCount + 1].BranchLength))
else
tnParent := Items.AddChildFirst(tnCurrent, tnOriginal.Parent.Text);
CreateUpNode(tnOriginal.Parent, tnParent{, tnSibling});
end;
end;
end;
end;