Рисуем деревья вертикально или горизонтально в C#

Пример Обработать общие события мыши TreeNode в C# показывает, как создать общий класс узлов, который может рисовать деревья с узлами, которые содержат что угодно. В этом примере каждый узел центрируется по его поддереву.

Этот пример изменяет это, чтобы вы могли рисовать деревья, ориентированные вертикально, как это делает элемент управления TreeView.

Основные отличия между этой программой и предыдущей версией заключаются в том, как узел упорядочивает и рисует сам. Следующий код показывает, как узел упорядочивается, если его ориентация вертикальна.

// Упорядочить поддерево вертикально.
public void ArrangeVertically(Graphics gr,
    float xmin, ref float ymin)
{
    // Посмотрим, насколько велик этот узел.
    SizeF my_size = Data.GetSize(gr, MyFont);
    my_size.Width += 3 * SpotRadius;

    // Установите положение этого узла.
    SpotCenter = new PointF(
        xmin + SpotRadius,
        ymin + (my_size.Height - 2 * SpotRadius) / 2);

    // Устанавливаем положение данных этого узла.
    DataCenter = new PointF(
        SpotCenter.X + SpotRadius + my_size.Width / 2,
        SpotCenter.Y);

    // Разрешить вертикальную комнату для этого узла.
    ymin += my_size.Height + VOffset;

    // Рекурсивно организуем наших детей.
    foreach (TreeNode child in Children)
    {
        // Упорядочить поддерево этого дочернего элемента.
        child.ArrangeVertically(gr, xmin + Indent, ref ymin);
    }
}

[draw trees]

[draw trees] ...

Затем код устанавливает центр данных. Эта позиция имеет то же положение Y, что и пятно, и сдвигается вправо на радиус пятна плюс половина оттянутой ширины данных.

Затем код обновляет допустимое минимальное значение Y ymin и рекурсивно вызывает методы дочерних узлов ArrangeVertically, чтобы упорядочить дочерние узлы.

Если вы сравните это с кодом, используемым в предыдущем примере, чтобы упорядочить дерево по горизонтали, вы обнаружите, что это намного проще. (Этот код также включен в этот метод ArrangeHorizontally этого примера.)

Когда программа рисует деревья, она использует два шага. Сначала он рисует связи между узлами, а затем сам рисует узлы. Следующий код показывает, как класс TreeNode рисует ссылки для вертикально ориентированного дерева.

// Нарисуйте ссылки для поддерева, внедренного на этом узле.
private void DrawSubtreeLinksVertical(Graphics gr)
{
    foreach (TreeNode child in Children)
    {
        // Нарисуем связь между этим узлом этого дочернего элемента.
        gr.DrawLine(MyPen, SpotCenter.X, SpotCenter.Y,
            SpotCenter.X, child.SpotCenter.Y);
        gr.DrawLine(MyPen, SpotCenter.X, child.SpotCenter.Y,
            child.SpotCenter.X, child.SpotCenter.Y);

        // Рекурсивно заставить ребёнка рисовать узлы его поддерева.
        child.DrawSubtreeLinksVertical(gr);
    }
}

Для каждого из дочерних узлов этот код рисует вертикальную линию от пятна узла до положения слева от точки ребенка. Затем он рисует линию от этой позиции до места ребенка. Код заканчивается рекурсивным вызовом метода child DrawSubtreeLinksVertical для рисования ссылок для поддерева child.

Следующий код показывает, как программа рисует сами узлы.

// Нарисуйте узлы для поддерева, внедренного в этот узел.
private void DrawSubtreeNodes(Graphics gr)
{
    // Рисуем этот узел.
    Data.Draw(DataCenter.X, DataCenter.Y, gr,
        MyPen, BgBrush, FontBrush, MyFont);

    // Если вы ориентированы вертикально, нарисуйте пятно узла.
    if (Orientation == TreeNode>T>.Orientations.Vertical)
    {
        RectangleF rect = new RectangleF(
            SpotCenter.X - SpotRadius, SpotCenter.Y - SpotRadius,
            2 * SpotRadius, 2 * SpotRadius);
        if (Children.Count > 0)
        {
            gr.FillEllipse(Brushes.LightBlue, rect);
        }
        else
        {
            gr.FillEllipse(Brushes.Orange, rect);
        }
        gr.DrawEllipse(MyPen, rect);
    }

    // Рекурсивно заставить ребёнка рисовать узлы его поддерева.
    foreach (TreeNode child in Children)
    {
        child.DrawSubtreeNodes(gr);
    }
}

Сначала код вызывает метод Draw объекта узла Data, чтобы сделать сам объект. Затем, если ориентация узла вертикальна, код рисует пятно слева от узла. Он заполняет пятна узлов листа оранжевым, а пятна нелистовых узлов - светло-голубыми.

Источник: http://csharphelper.com/blog/2016/08/draw-trees-vertically-or-horizontally-in-c/

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Adblock
detector