2012-04-03 377 views
11

我必須畫很多Shape(大約二十萬)作爲[帆布] [2]的兒童。我在WPF應用程序中將它分爲兩​​部分:首先我通過設置每個部分的屬性(比如邊距,填充,寬度等等)來創建形狀,然後將形狀添加爲Canvas的子部分。如何提高畫布渲染性能?

MyCanvas.Children.Add(MyShape) 

現在我想提高第二部分的表現,因爲當我畫的形狀,我的應用程序被阻止的很長一段時間。所以我試圖用Dispatcher及其方法[BeginInvoke] [4]與不同的[優先級] [5]:只有當我使用主應用程序不會阻止的後臺優先級時,否則應用程序將保持阻塞狀態,並且「圖片」爲直到所有形狀都添加到我的畫布中才會顯示,但如果使用背景優先級,顯然一切都會變慢。我也嘗試創建一個新的線程,而不是使用Dispatcher,但沒有發生重大變化。

我該如何解決這個問題,並且在向Canvas添加我的圖形時,通常可以提高應用程序的性能?

謝謝。

+0

你試過DrawingVisual嗎? – 2012-04-03 18:51:01

+0

不可以。您可以給我一個如何使用DrawingVisual而不是像Ellipse或Path之類的Shape的例子。例如,如何添加到我的Canvas [this](http://msdn.microsoft.com/zh-cn/library/ms745546.aspx)使用DrawingVisual的路徑? – gliderkite 2012-04-03 20:56:55

+0

是的,Google上有一些很棒的信息。這裏有一個鏈接,讓你開始:http://msdn.microsoft.com/en-us/magazine/dd483292.aspx – 2012-04-03 20:59:02

回答

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個視覺效果。 – 2012-05-04 08:48:28

+0

那麼什麼是處理十萬個矢量圖形元素? – gliderkite 2012-05-04 08:54:58

+0

查看Q和AI鏈接:http://stackoverflow.com/questions/8713864/high-performance-graphics-using-the-wpf-visual-layer/8714107#8714107 – 2012-05-04 08:55:55

1

這就是很多的UIElements,可能不會給你想要的那種表現。你需要能夠與你正在渲染的每個元素進行交互嗎?如果不是,我強烈建議您使用WriteableBitmap來代替。如果你需要繪製形狀並且不想自己創建所有的邏輯(誰願意?),check out the WriteableBitmapEx project over on CodePlex

+0

我需要與所有形狀交互,我也使用形狀,因爲「圖片」是一個矢量圖形圖像(圖像可以縮放 - 縮放 - 任何數量,而不會降低質量)。用WritableBitmapEx我可以做同樣的事情? – gliderkite 2012-04-03 17:40:04

+1

我不會使用Shape,我會使用DrawingVisual。你能把這些細節添加到你的問題嗎?我會考慮並修改我的答案。 – 2012-04-03 17:42:28

3

同意,如果你想繪製數百萬的元素,你根本無法在WPF中完成它。所提到的WriteableBitmapEx是一個很好的選擇。

請參閱this related question它深入瞭解WPF中的高性能圖形和可用的替代方案。

如果您只需使用Canvas,請查看此ZoomableApplication2 - A million items。這是一個基於Canvas的演示,它大量使用虛擬化技術,在畫布上獲得1,000,000個UIElements的合理性能。

+0

這是可能的,因爲我必須繪製大約1/2十萬個元素(正如我寫的),並且我已經完成了使用我的答案(自從我問這個問題已經很長時間了),無論如何感謝您的答案,但是位圖不是矢量圖形。 – gliderkite 2012-05-04 08:49:46

1

這可能有點不相干,如果您有這種感覺,我很抱歉,但希望能爲其他用戶留下一些亮光,我將分享這個珍聞。

我們對用於捕獲簽名的Canvas控件有一些性能問題。捕捉非常鋸齒,因此我們無法畫出曲線。事實證明,這與UI元素上正在生成陰影的樣式有關。禁用陰影效果解決了我們的問題。

+0

感謝您的這一點,我遇到了在網格上繪製大量線條的性能問題,並且通過去除我的陰影效果,沒有一點都沒有! – Cyral 2015-01-23 22:14:06