所以有一个很棒的开源tutorial on creating TreeNode class。太棒了。但我想知道如何更改其编配功能以使其绘制indented树?
这是功能:
// Arrange the node and its children in the allowed area.
// Set xmin to indicate the right edge of our subtree.
// Set ymin to indicate the bottom edge of our subtree.
public void Arrange(Graphics gr, ref float xmin, ref float ymin)
{
// See how big this node is.
SizeF my_size = Data.GetSize(gr, MyFont);
// Recursively arrange our children,
// allowing room for this node.
float x = xmin;
float biggest_ymin = ymin + my_size.Height;
float subtree_ymin = ymin + my_size.Height + Voffset;
foreach (TreeNode<T> child in Children)
{
// Arrange this child's subtree.
float child_ymin = subtree_ymin;
child.Arrange(gr, ref x, ref child_ymin);
// See if this increases the biggest ymin value.
if (biggest_ymin < child_ymin) biggest_ymin = child_ymin;
// Allow room before the next sibling.
x += Hoffset;
}
// Remove the spacing after the last child.
if (Children.Count > 0) x -= Hoffset;
// See if this node is wider than the subtree under it.
float subtree_width = x - xmin;
if (my_size.Width > subtree_width)
{
// Center the subtree under this node.
// Make the children rearrange themselves
// moved to center their subtrees.
x = xmin + (my_size.Width - subtree_width) / 2;
foreach (TreeNode<T> child in Children)
{
// Arrange this child's subtree.
child.Arrange(gr, ref x, ref subtree_ymin);
// Allow room before the next sibling.
x += Hoffset;
}
// The subtree's width is this node's width.
subtree_width = my_size.Width;
}
// Set this node's center position.
Center = new PointF(
xmin + subtree_width / 2,
ymin + my_size.Height / 2);
// Increase xmin to allow room for
// the subtree before returning.
xmin += subtree_width;
// Set the return value for ymin.
ymin = biggest_ymin;
}
现在的样子:
缩进树的外观(基于DmitryG s grate answer的图像):
那么..如何让它以缩进的形式绘制图形?
答案 0 :(得分:1)
您可以递归渲染树,并跟踪您所处的深度以确定缩进级别。
如:
rootNode.RenderTree(0, 0); // Recursively draw root node at (0,0)
...
void RenderTree(int depth, ref int y)
{
// Draw this Node at position (depth * indentAmount, y)
... whatever you like here to get the style of items that you want...
depth++; // Increase indent level (X pos) for all children
y += thisNode.Height; // After drawing each item, move down the page
// Now recurse to draw all children
foreach (Node childNode in Children)
childNode.RenderTree(depth, ref y);
}
绘制连接线还有一些工作要做(你需要使用深度级别来告诉你要绘制多少行),但基本上就是这样。
请注意,我们将y作为ref
传递,以便每个项目按顺序向下移动绘图位置,但我们按值传递深度,因为它对于树的同一级别的所有子项都是常量。
(请注意,这个伪代码与您的Arrange方法非常相似 - 只需更改名称并传入Graphics对象,它几乎就是一个插件替换。我会留给您研究如何绘制但每个项目的线条,圆圈和文字: - )
答案 1 :(得分:1)
我已经为缩进树排列修改了TreeNode.Arrange()方法 现在它看起来像这样:
public void Arrange(Graphics gr, ref float xmin, ref float ymin) {
// See how big this node is.
SizeF my_size = Data.GetSize(gr, MyFont);
// Recursively arrange our children,
// allowing room for this node.
float y = ymin + my_size.Height;
float biggest_xmin = xmin + my_size.Width;
float subtree_xmin = xmin + my_size.Width + Hoffset;
foreach(TreeNode<T> child in Children) {
// Arrange this child's subtree.
float child_xmin = subtree_xmin;
child.Arrange(gr, ref child_xmin, ref y);
// See if this increases the biggest ymin value.
if(biggest_xmin < child_xmin) biggest_xmin = child_xmin;
// Allow room before the next sibling.
y += Voffset;
}
// Remove the spacing after the last child.
if(Children.Count > 0) y -= Voffset;
// See if this node is wider than the subtree under it.
float subtree_height = y - ymin;
if(my_size.Height > subtree_height) {
y = ymin + (my_size.Height - subtree_height) / 2;
foreach(TreeNode<T> child in Children) {
// Arrange this child's subtree.
child.Arrange(gr, ref subtree_xmin, ref y);
y += Voffset;
}
subtree_height = my_size.Height;
}
// Set this node's center position.
Center = new PointF(xmin + my_size.Width / 2, ymin + my_size.Height / 2);
ymin += subtree_height;
xmin = biggest_xmin;
}
注意,DrawSubtreLinks()方法也已被修改:
private void DrawSubtreeLinks(Graphics gr) {
foreach(TreeNode<T> child in Children) {
PointF p = new PointF(Center.X, child.Center.Y);
gr.DrawLine(MyPen, Center, p);
gr.DrawLine(MyPen, p, child.Center);
child.DrawSubtreeLinks(gr);
}
}
答案 2 :(得分:0)
实际的缩进边距和内容将需要一些试验和错误,但这应该作为一个基本的伪算法
创建一个存储treeNode,Depth和PrevSiblingIndex的类,然后使用它来为所有树节点填充单个数组。所以当你完成时,数组中节点的索引是它的行号(y偏移量),深度是它的缩进(x偏移量),如果PrevSiblingIndex为null,则只需要连接一行到父母。如果它不为null,则需要连接当前行中的一行,直到它的prevSibling。
答案 3 :(得分:0)
TreeNodes有一个.Level属性,可用于确定缩进节点的距离。
http://msdn.microsoft.com/en-us/library/system.windows.forms.treenode.level.aspx