2012-04-03 9 views
11

Мне нужно нарисовать много Shape (около 1/2 сотни тысяч) в качестве детей [Холст] [2]. Я делаю это в своем приложении WPF, разделяя работу на две части: во-первых, я создаю фигуры, устанавливая свойства каждого из них (например, Margin, Fill, Width и т. Д.) После добавления фигур в качестве дочерних элементов Canvas.Как улучшить производительность рендеринга Canvas?

MyCanvas.Children.Add(MyShape) 

Теперь я хочу, чтобы улучшить производительность второй части, потому что, когда я рисовать фигуры мое приложение блокируется в течение длительного периода времени. Поэтому я попытался использовать Dispatcher и его метод [BeginInvoke] [4] с разными [приоритетами] [5]: только если я использую приоритет фона, основное приложение не блокируется, в противном случае приложение остается заблокированным, а «картинка» - не отображается, пока все фигуры не будут добавлены в мой холст, но если я использую приоритет фона, очевидно, все будет медленнее. Я также попытался создать новый поток вместо использования диспетчера, но существенных изменений не произошло.

Как я могу исправить эту проблему и вообще улучшить производительность моего приложения, когда добавляю свои фигуры в Canvas?

Спасибо.

+0

Вы попробовали DrawingVisual? –

+0

Нет. Не могли бы вы привести пример использования DrawingVisual вместо формы, например Ellipse или Path. Например, как я могу добавить на мой Canvas [this] (http://msdn.microsoft.com/en-us/library/ms745546.aspx) путь с помощью DrawingVisual? – gliderkite

+0

Да, есть отличная информация о Google. Вот ссылка, с которой вы начали: http://msdn.microsoft.com/en-us/magazine/dd483292.aspx –

ответ

7

Необходимо использовать Visual объектов вместо Shape; в частности, как было предложено, DrawingVisual: визуальный объект, который можно использовать для визуализации векторной графики. Фактически, как написано в библиотеке MSDN:

DrawingVisual - это легкий класс рисования, который используется для визуализации фигур, изображений или текста. Этот класс считается легким, потому что он не обеспечивает компоновку, ввод, фокусировку или обработку событий, что повышает его производительность. По этой причине рисунки идеально подходят для фона и клипа.

Так, например, для создания DrawingVisual, который содержит прямоугольник:

private DrawingVisual CreateDrawingVisualRectangle() 
{ 
    DrawingVisual drawingVisual = new DrawingVisual(); 

    // Retrieve the DrawingContext in order to create new drawing content. 
    DrawingContext drawingContext = drawingVisual.RenderOpen(); 

    // Create a rectangle and draw it in the DrawingContext. 
    Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80)); 
    drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null, rect); 

    // Persist the drawing content. 
    drawingContext.Close(); 

    return drawingVisual; 
} 

Для того, чтобы использовать объекты DrawingVisual, вам нужно создать хост-контейнер для объектов. Объект контейнера-хоста должен быть получен из класса FrameworkElement, который обеспечивает поддержку макета и обработки событий, которой не обладает класс DrawingVisual. Когда вы создаете объект контейнера-хоста для визуальных объектов, вам необходимо сохранить ссылки на визуальные объекты в VisualCollection.

public class MyVisualHost : FrameworkElement 
{ 
    // Create a collection of child visual objects. 
    private VisualCollection _children; 

    public MyVisualHost() 
    { 
     _children = new VisualCollection(this); 
     _children.Add(CreateDrawingVisualRectangle()); 

     // Add the event handler for MouseLeftButtonUp. 
     this.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(MyVisualHost_MouseLeftButtonUp); 
    } 
} 

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

+3

Это поможет, незначительно, однако WPF не предназначен для обработки 50 000 визуальных изображений любого типа. –

+0

Итак, что предназначено для обработки сто тысяч элементов векторной графики? – gliderkite

+0

См. Q и AI, связанные с: http://stackoverflow.com/questions/8713864/high-performance-graphics-using-the-wpf-visual-layer/8714107#8714107 –

1

Это много из UIElements и, вероятно, не даст такого качества, которое вы ищете. Вам нужно иметь возможность взаимодействовать с каждым из элементов, которые вы визуализируете? Если нет, я бы настоятельно рекомендовал вместо этого использовать WriteableBitmap. Если вам нужно нарисовать фигуры и не хотите самостоятельно создавать всю эту логику (кто захочет?), check out the WriteableBitmapEx project over on CodePlex.

+0

Мне нужно взаимодействовать со всеми формами, также я использую Shape, потому что «изображение» - это векторное графическое изображение (изображение можно масштабировать - с увеличением - на любую величину без ухудшения качества). С WritableBitmapEx я мог бы сделать то же самое? – gliderkite

+1

Я бы не использовал Shape, я бы использовал DrawingVisual. Можете ли вы добавить эти данные на свой вопрос, пожалуйста? Я подумаю об этом и пересмотрю свой ответ. –

3

Согласен, что если вы хотите нарисовать миллионы элементов, вы просто не сможете это сделать в WPF. WriteableBitmapEx, как упоминалось, является хорошей альтернативой.

См. this related question, который углубляется в высокоэффективную графику в WPF и доступных альтернативах.

Если вы просто должны использовать Холст, ознакомьтесь с этим ZoomableApplication2 - A million items. Это демонстрация на основе Canvas, которая сильно использует виртуализацию для получения разумной производительности с 1,000,000 UIElements на холсте.

+0

это возможно, потому что я должен нарисовать около 1/2 сотни тысяч элементов (как я писал), и я сделал, используя свой ответ (прошло много времени с тех пор, как я задал вопрос), в любом случае спасибо за ваш ответ, но растровое изображение не является векторной графикой. – gliderkite

1

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

У нас были проблемы с производительностью с помощью элемента управления Canvas, используемого для захвата подписей. Захват был очень зазубрен, и в результате мы не могли рисовать кривые линии. Оказалось, что это связано с тем, что стиль создавал тени для элементов пользовательского интерфейса. Отключение эффекта drop-shadow решило нашу проблему.

+0

Спасибо за это. У меня возникли проблемы с производительностью, рисующие большое количество строк на сетке, и, удалив эффект тени, нет отставание вообще! – Cyral

Смежные вопросы