如何在 WPF 中尽可能高效地绘制图形
我正在创建一个严重依赖图节点树的工具。当前的实现是用 Java 完成的,我将其移植到 C# 上的通用代码库,因此它可以由各种渲染实现使用,而且因为我想使用 WPF 的强大功能来实现用户友好的界面。
经过一天的浏览,我发现了通过 WPF 绘制矢量图形的各种方法。
这个人谈论 WPF 开发人员可以选择的不同层。因为我想首先纯粹使用 WPF 进行渲染,所以我想在“视觉层”上工作。
然后我遇到了这样的事情: DrawingVisual, 几何绘图, FrameworkElement / UIElement / Shapes
因此,我对最终完成的所有不同实现感到有点不知所措以完全不同的方式相同。
Graph-Node 库已被移植到 C# 中,并包含其所有逻辑(包括碰撞检测和鼠标拖动)。由于它是根据图形渲染器(如 XNA、SlimDX、OpenTK 等)制作的,因此在性能方面实现 WPF 渲染器的最佳方式是什么(例如,它将绘制图形库告诉它的任何内容) 基本上,生成的 WPF 控件充当画布
,但它必须是超级轻量级的,除了为我提供绘制圆形、线条和其他形状的方法之外,没有任何简洁的 WPF 功能:)
编辑:
我基本上想要知道:该怎么走呢?我是否可以将 Canvas 扩展为图形的“主机”,然后添加 UIElement 的自定义实现?或者我可以有一门可以绘制所有东西的课程(例如,一个超级超级图形)。很像重写 GDI 中的 OnPaint 或 Java 中的 Paint 方法(它提供了一个 Graphics 对象来执行所有操作)。
I am creating a tool which relies heavily on graph-node trees. The current implementation is done in Java and I'm porting it to a generic code-base on C#, so it can be used by various rendering implementations and also because I want to use the power of WPF for a user-friendly interface.
After browsing around for a day, I came across various methods to draw Vector-graphics through WPF.
This guy speaks about different layers within WPF developers can choose from. As I want to use WPF PURELY for his rendering at first, I want to work on the "Visual Layer".
I then came across things like:
DrawingVisual,
GeometryDrawing,
FrameworkElement / UIElement / Shapes
So, I'm a bit overwhelmed by all the different implementations that do eventually the same in totally different ways.
The Graph-Node library has been ported to C# already with all it's logic (including collision detection and dragging with mouse). As it is made with graphic-renderers in mind (like XNA, SlimDX, OpenTK, etc.), what would be the best way in terms of performance to implement a WPF renderer (as in, it will draw whatever the graph library tells it to draw?
Basically, the resulting WPF control acts as a canvas, but it has to be SUPER lightweight and not have any neat WPF features besides providing me a way to draw my circles, lines and other shapes :)
EDIT:
I basically want to know: What is the way to go? Do I extend Canvas as "Host" for my graphics and then add my custom implementation of a UIElement? Or can I have one class which can draw EVERYTHING (as in, one mega super ultra graphic). Much like overriding OnPaint in GDI or Paint-method in Java (which gives a Graphics object to do everything with).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我建议阅读 优化性能:2D 图形和成像。
一般来说,
Drawing
对象的重量比Shapes
轻。这可能就是您想要使用的。I'd recommend reading Optimizing Performance: 2D Graphics and Imaging.
Basically,
Drawing
objects will be lighter weight thanShapes
, in general. This is probably what you want to use.一般来说,较低级别的服务可以获得更好的性能。在
WPF
中,这意味着Drawing
对象系列。您获得的所有内容是:Drawing
、DrawingGroup
、GeometryDrawing
、GlyphRunDrawing
、ImageDrawing
、和VideoDrawing
。然而,它们足以满足所有需求。使用这些类型对于 WPF 非常友好,因为Drawing
是 WPF 与 GPU 加速器交换的概念单元,如果可能的话,可能会在那里保留和管理它。这是可行的,因为Drawing
是用便携式矢量绘图基元表示的。然而,一旦您开始围绕
Drawings
重新构建应用程序,您可能需要与仍基于UIElement
、FrameworkElement将绘图包装为 FrameworkElement 的简单方法。
DrawingVisual
不是一个完整的解决方案,因为它仅派生自Visual
- 这意味着它仍然需要托管元素。以下类将直接托管任何 WPF
Drawing
,而不使用中间DrawingVisual
。我添加了对FrameworkElement
的Margin
属性的支持(如果未使用,不会造成性能损失),但除此之外就没有什么了。由于 WPF 的单个渲染线程,可以安全且轻松地缓存单个 TranslateTransform 对象来实现边距。我建议您只提供已冻结的图纸;事实上,在我使用的版本中,我在构造函数中有一个断言来实现这一效果。[编辑:] 这对于将 WPF
Drawing
插入到InlineUIContainer.Child
属性中也很有用(即使用TextBlock.InlinesCollection
来格式化内容) TextBlock 的功能更加丰富)。Generally, better performance is obtained with lower-level services. In
WPF
, this means theDrawing
family of objects. All you get are:Drawing
,DrawingGroup
,GeometryDrawing
,GlyphRunDrawing
,ImageDrawing
, andVideoDrawing
. However, they are sufficient for all needs. Using these types is very friendly with WPF becauseDrawing
is the conceptual unit that WPF exchanges with your GPU accelerator, possibly retaining and managing it there if possible. This works because theDrawing
is expressed in terms of portable vector drawing primitives.Once you start re-architecting your app around
Drawings
however, you might need some interop with your higher-level code which is still based onUIElement
,FrameworkElement
, etc. One thing that I haven't found built-in to WPF is a simple way to wrap a Drawing as a FrameworkElement in the lowest-overhead way possible.DrawingVisual
isn't a complete solution, because it only derives fromVisual
--meaning it still requires a hosting element.The following class will host any WPF
Drawing
directly without using an intermediateDrawingVisual
. I added support forFrameworkElement
'sMargin
property (with no performance penalty if unused) but little else. Because of WPF's single rendering thread it's safe and easy to cache a single TranslateTransform object to implement the margin. I'd recommend that you supply only drawings which have been Frozen; in fact, in the version that I use, I have an assert to that effect in the constructor.[edit:] This is also useful for inserting a WPF
Drawing
into theInlineUIContainer.Child
property (i.e. usingTextBlock.InlinesCollection
to format the contents of the TextBlock more richly).DrawingVisual 似乎是一个有效的选择:
来源:使用 DrawingVisual 对象
所以这似乎绝对是您所要求的,超轻帆布。
the DrawingVisual seems to be a valid choice:
source: Using DrawingVisual Objects
so this seems to be absolutely what you ask, a Canvas SUPER lightweight.