2011-05-11 218 views
6

所以,我用winForms .CreateGraphics绘制了各种不同的东西,从线到框到图像。这是非常活泼和回应。相当于wpf中的CreateGraphics

我想学习WPF在C#

我发现,WPF允许我“添加”矩形物体在画布将正常显示。不过,我有时候会画数十万个矩形,画图速度会变得非常慢,而当我移动矩形中的一个时,UI变得不那么活泼。

在winForms中直接绘制元素的速度并不是很快,但无论绘制多少,它都是一致的。

是否有类似的解决方案来做这件事在WPF?

我试着添加一个linq到System.Drawing,它给了我一个Graphics对象,但我试过的wpf元素都没有.CreateGraphics()方法。

+3

圣@#%(.CreateGraphics不存在WPF无论??????每一天我找到新的理由使用WPF作为一种形式的选择后悔,这就像使用取胜的形式,并尽一切易如反掌或者使用WPF和gl搜索10个小时如何做一些简单的事情 – 2012-04-27 13:44:58

回答

2

您需要创建一个覆盖OnRender的控件,并在那里进行绘图。你没有办法绘制另一个控件,但控件可以绘制自己。

此外,请记住,WPF使用retained graphics,所以如果您更改了某些内容,则需要根据需要使视觉无效。

编辑:

喜欢的东西:

public class MyControl : Control { 

    public MyControl() { 
     this.Rects = new ObservableCollection<Rect>(); 
     // TODO: attach to CollectionChanged to know when to invalidate visual 
    } 

    public ObservableCollection<Rect> Rects { get; private set; } 

    protected override void OnRender(DrawingContext dc) { 
     SolidColorBrush mySolidColorBrush = new SolidColorBrush(); 
     mySolidColorBrush.Color = Colors.LimeGreen; 
     Pen myPen = new Pen(Brushes.Blue, 10); 

     foreach (Rect rect in this.Rects) 
      dc.DrawRectangle(mySolidColorBrush, myPen, rect); 
    } 
} 
+0

我想出了无效,以及如何强制重绘。如果我有一个名为'canvas的Canvas对象,你愿意提供一个简短的片段吗? ',以及如何覆盖只有该对象的'OnRender()'方法? – ohmusama 2011-05-11 17:57:25

+0

@ohmusama - 无论如何,你不需要使用类似于Canvas的东西。你的控件只会渲染矩形,但实际上并不会有任何UIElement矩形(只是Rect),OnRender链接显示一个示例控件 – CodeNaked 2011-05-11 18:03:26

+0

这是否需要我扩展现有的canvas类以覆盖它?如果我的新canvas类是'c lass MyCanvas:Canvas' in yaml我会创建一个''而不是''如果我理解了一切正确的话? – ohmusama 2011-05-11 18:13:46

2

正如有人说,WPF使用一个保留图形的方法让你真正在内存中创建100000个矩形对象,然后绘制所有的人。减速可能是由于垃圾收集和一般内存问题。

除了重写OnRender方法,还有一些你可以看看的东西。

  1. 使用GDI方法的熟悉,然后将结果写入一个WPF WriteableBitmap的

  2. 使用D3DImage并采取硬件加速的优势绘制矩形到图像中的后台线程。这要求您了解DirectX(或Direct2D)库。如果你对这种方法感兴趣,我会建议看看SlimDx。

4

WPF使用与WinForms不同的图形操作模型。

使用WinForms,您可以直接编辑屏幕上的像素。绘制像素后,矩形的概念会丢失。绘制像素是一个非常快速的操作。

使用WPF,您不控制屏幕上的像素。 DirectDraw是。 DirectDraw是一个基于矢量的合成引擎。你不画像素。您定义矢量形状(或视觉效果)。即使在图像呈现在屏幕上之后,形状或矩形的概念仍为“保留”。当您添加一个与其他矩形重叠的新矩形时,所有其他矩形都需要进行重新渲染。这可能是您的表现正在放缓的地方。这在使用WinForms时不会发生。

您可以通过覆盖的OnRender有点改善WPF的性能。您可以剪掉Rectangle对象的开销并直接提供视觉效果。但是,您仍然没有在屏幕上绘制像素。您正在定义DirectDraw用于呈现图像的形状。在这方面,OnRender名称可能有点误导。

我相信你可以找到大量的技巧,以提高在WPF应用程序的性能。还有一些方法仍然可以绘制像素 - 但这有点击败了WPF的观点。

你在做什么,需要数千个矩形?

+1

制作迷宫:http://imgur.com/a/27PPs#5W1Ou和http:// imgur。 COM/ftFOv – ohmusama 2011-05-11 18:17:03

2

问题是大多数likeley不是WPF无法呈现的图形对象1000,但您创建和添加项目太远了WPF对象层次结构。它毕竟使用GPU来处理所有的图形工作。

只要你开始基于后一个“UIElement”添加对象,你就应该尽可能的把对象添加到“Visual”类中,你要求WPF跟踪每个对象的用户点击,悬停等等,不只是画出来。

+0

我加入'Rectangle's到'Canvas'这是MainWindow'的'这里的/你会如何添加这些矩形的孩子。我是用“myCanvas.Add(myRectangle)' – ohmusama 2011-05-11 20:08:52

+0

其实WPF矩形会似乎是一个不错的选择;它是框架最低级别的形状绘制的东西,但是它继承自FrameworkElement,它已经得到了一些命中测试/鼠标悬停在/ etc的包装上,您可能想要考虑创建自己的自定义控件(基于Visual如果你能)为可以去除尽可能多的运行时UI控件行李。 – 2011-05-11 20:48:06

+0

有什么特别的,我需要做的,使自己的自定义控制继承视觉,使其可用,或者一个链接就足够了。 – ohmusama 2011-05-11 21:06:39