Как заставить нарисованный владельцем класс TreeNode упорядочить элементы, как в отступе дерева? - PullRequest
1 голос
/ 22 октября 2011

Итак, существует замечательное учебное пособие с открытым исходным кодом по созданию класса TreeNode . Это просто супер. Но мне интересно, как изменить его функцию Arrange, чтобы она рисовала дерево с отступом ?

Вот функция:

// 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;
}

Как это выглядит сейчас:

enter image description here

Как выглядит отступное дерево (изображение на основе Ответ Дмитрия Г * ):

enter image description here

Итак .. Как мне заставить его нарисовать график с отступом?

Ответы [ 4 ]

1 голос
/ 25 октября 2011

Я изменил метод 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 () также был изменен:1005 *

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);
    }
}
1 голос
/ 25 октября 2011

Вы можете отрисовать дерево рекурсивно и отслеживать глубину, на которой вы находитесь, чтобы определить уровень отступа.

Как в:

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, и он в значительной степени заменяет плагин. Я оставлю вам решать, как рисовать линии, круги и текст для каждого элемента, хотя: -)

0 голосов
/ 24 октября 2011

TreeNodes имеют свойство .Level, которое вы можете использовать, чтобы определить, как далеко отступать ваш узел.

http://msdn.microsoft.com/en-us/library/system.windows.forms.treenode.level.aspx

0 голосов
/ 24 октября 2011

Фактические отступы и прочее потребуют некоторых проб и ошибок, но это должно работать как основной псевдоалгоритм

Создайте класс, который хранит treeNode, Depth и PrevSiblingIndex, а затем используйте его для заполненияодин массив для всех узлов дерева.Итак, когда вы закончите, индекс узла в массиве - это его номер строки (смещение по оси y), глубина - это его отступ (смещение по оси x), а если PrevSiblingIndex равен нулю, то вам просто нужно подключить строку кродитель.Если оно не равно нулю, вам нужно подключить строку из текущей строки, вплоть до прежней.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...