【问题标题】:WPF drawing performance with large numbers of elements具有大量元素的 WPF 绘图性能
【发布时间】:2011-01-04 10:16:17
【问题描述】:

我正在尝试在 WPF 中创建一个自定义控件来显示 game of go 的游戏树(请参阅 here 了解其外观)。我或多或少地让它在布置节点时工作,但我发现的一个问题是,当节点的数量大于大约30. 由于围棋平均由大约 200 步棋组成(更不用说玩家可能会分叉的其他分支),这在任何现实游戏中都将是一个相当大的问题。

目前,我正在为游戏节点(每个都是一个带有阴影位图效果和一些文本注释的椭圆)和树中的弧线使用单独的用户控件,所有这些都绝对定位在画布。

布局算法不是这样的问题,因为它只需要在创建新分支时执行(否则节点可以直接添加到其父节点下方,因此不需要重新定位其他节点)。主要问题很简单,就是对这个画布及其元素的任何类型的操作都非常缓慢,大概是因为它有很多子元素。随着树的宽度和复杂性的增加,它显然会变慢,因为有更多的弧和节点。

我的问题:绘制这样一个大型/复杂结构的正确方法是,它不会随着它的增长而渲染得太慢?

编辑:这与my other question有关。

编辑:这是我用于节点的用户控件的标记:

<UserControl x:Class="Go.UI.GameNodeMarker"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Go.UI"
             xmlns:wpftools="clr-namespace:WpfTools.Extensions;assembly=WpfTools"
             x:Name="_This">
    <UserControl.Resources>
        <!-- Some brushes, resources, etc. are omitted -->
        <Style x:Key="StoneStyle" TargetType="{x:Type Ellipse}">
            <Setter Property="StrokeThickness" Value="0"/>
            <Setter Property="BitmapEffect" Value="{StaticResource StoneEffect}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=_This, Path=StoneColour}"  Value="Black">
                    <Setter Property="Fill" Value="{StaticResource BlackStoneBrush}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding ElementName=_This, Path=StoneColour}" Value="White">
                    <Setter Property="Fill" Value="{StaticResource WhiteStoneBrush}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding ElementName=_This, Path=IsEmpty}" Value="True">
                    <Setter Property="Fill" Value="{StaticResource EmptyBrush}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </UserControl.Resources>
    <Grid>
        <Ellipse Style="{StaticResource StoneStyle}"/>
        <TextBlock Text="{Binding ElementName=_This, Path=Text}"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"
                   FontWeight="Medium"/>
    </Grid>
</UserControl>

这些被动态添加到画布中以绘制树。

【问题讨论】:

    标签: c# wpf performance drawing baduk


    【解决方案1】:

    我不知道你是否会喜欢我的建议,因为它看起来很难看,但你可以尝试通过以下方式关闭抗锯齿:

    将当前窗口的 RenderOptions.EdgeMode 设置为“未指定”(无抗锯齿)

    你应该得到更好的性能,但有些粗略的绘图。

    祝你好运! 埃里克

    【讨论】:

      【解决方案2】:

      我知道这可能无法真正回答问题,但我认为值得指出。

      WPF4 将在不久的将来推出,它将支持元素图形的缓存,在许多情况下无需重绘。在您想要利用这一点的元素上添加几个属性,您就可以开始了。如果您最终使用它,请尽量避免不必要的动画。如果屏幕上的每个元素都需要在每一帧上重绘,那么缓存是没有意义的。滚动动画会很好。

      【讨论】:

      • 是的。我也无法想象从现在开始的发布日期会很长。不过不要经过我。 =p
      【解决方案3】:

      渲染控件实际上非常昂贵。如果您在客户区进行自定义绘图(自己绘制项目而不是放置控件),您将看到您的性能显着提高。

      这是我在从事此类工作时的一次又一次经历。如果您需要十几个控件,请选择所有者绘制。

      顺便说一句,不要让自定义绘图吓倒您。它并不比动态放置控件复杂多少。

      链接到custom WPF drawing sample

      【讨论】:

      • 自定义绘图是指将相关形状(椭圆等)放在GameTree 控件的代码隐藏中,而不是放在单独的用户控件中,或者做一些较低级别的事情?你能给我一个简单的例子或解释它的链接吗?谢谢!
      • ++ 是的。自己画,如果有闪烁,画到内存位图,分块传输到窗口。
      • 这是一个解释如何绘制基本 WPF 形状的链接:msdn.microsoft.com/en-us/library/ms747393.aspx 在您的情况下,您需要结合绘制阴影圆圈,然后是线条,然后是带边框的填充圆圈,正文。起初它似乎令人生畏,但玩它。您会发现使用 .Net 绘图有多么有趣!
      • 那么开销仅与用户控件的创建/呈现有关吗?我基本上以与您发布的链接相同的方式使用线条和省略号来创建我的游戏节点用户控件(请参阅我的更新)。由树控件本身手动完成这一切会快得多吗?
      【解决方案4】:

      我自己是 4-D 围棋选手 :) 您可能想要创建棋盘的位图,然后重绘已更改的部分。

      【讨论】:

      • 问题是我希望游戏树中的石头和节点是交互的,所以用户控件提供的自动命中测试等很有用。
      • 是的,当您将 Go 扩展到不同的棋盘几何形状时,它会非常有趣!我编写了游戏引擎以允许具有任意几何形状的棋盘和任意数量的玩家。怎么玩4D?视觉投影到 3D/2D 空间?
      • 您可以在 2D 中绘制 4D 空间,就像在 2D 中绘制 3D 空间一样。尝试绘制 4D 立方体 - 只需使用与从 2D 立方体(正方形)绘制 3D 立方体相同的概括即可。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-29
      • 2012-03-17
      • 2013-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多