【问题标题】:How can I avoid anti aliasing with WPF?如何避免使用 WPF 进行抗锯齿?
【发布时间】:2009-12-16 23:20:30
【问题描述】:

WPF 的一大问题是抗锯齿。 事实上,这就是在 WPF 4.0 中引入 UseLayoutRending 的原因。 但是,在以下示例中它对我不起作用:

<StackPanel UseLayoutRounding="True" TextOptions.TextFormattingMode="Display" >
    <Line X1="0" Y1="0" X2="200" Y2="0" StrokeThickness="1" Stroke="Black" SnapsToDevicePixels="True" UseLayoutRounding="True"></Line>
    <Line X1="0" Y1="1.5" X2="200" Y2="1.5" StrokeThickness="1" Stroke="Black" SnapsToDevicePixels="True" UseLayoutRounding="True"></Line>
    <Line X1="0" Y1="3.5" X2="200" Y2="3.5" StrokeThickness="1" Stroke="Black" SnapsToDevicePixels="True" UseLayoutRounding="True"></Line>
    <Line X1="0" Y1="7" X2="200" Y2="7" StrokeThickness="1" Stroke="Black" SnapsToDevicePixels="True" UseLayoutRounding="True"></Line>
    <Line X1="0" Y1="9" X2="200" Y2="9" StrokeThickness="1" Stroke="Black" SnapsToDevicePixels="True" UseLayoutRounding="True"></Line>
</StackPanel>

最后两行仍然模糊。 (我使用的是 Windows 7)

有什么办法吗?

或者它是 WPF 4.0 测试版中的一个错误?

【问题讨论】:

    标签: wpf antialiasing


    【解决方案1】:

    Floele 的回答显示了正确的方向,但答案并不完整。只需将 y 值设置为半个像素,例如Y1="7" -> Y1="7.5"

    这就是第二行和第三行不模糊的原因。

    【讨论】:

      【解决方案2】:

      在 WPF 中让线条看起来很清晰是非常困难的!有时……似乎也需要一点黑魔法!

      我认为 floele 和 Kimke 的回答指向了正确的方向。也就是说,通常您会希望将单个像素线放在 0.5 像素的边界上……考虑到它绘制线的方式(一半在一侧,另一侧在另一侧)。

      但是,它也不总是那么简单。例如,它还取决于周围的 xaml。例如,尝试此代码并在执行时调整大小:

      <Canvas HorizontalAlignment="Center" VerticalAlignment="Center">
          <Line X1="0" Y1="5" X2="200" Y2="5" StrokeThickness="1" Stroke="Black" UseLayoutRounding="True"/>
          <Line X1="0" Y1="15" X2="200" Y2="15" StrokeThickness="1" Stroke="Black" UseLayoutRounding="True"/>
      </Canvas>
      

      然后,试试这段代码(同样,调整大小):

      <Canvas HorizontalAlignment="Center" VerticalAlignment="Center" UseLayoutRounding="True">
          <Line X1="0" Y1="5" X2="200" Y2="5" StrokeThickness="1" Stroke="Black"/>
          <Line X1="0" Y1="15" X2="200" Y2="15" StrokeThickness="1" Stroke="Black"/>
      </Canvas>
      

      两个 sn-ps 之间的唯一区别是第一个在 Lines 上使用 UseLayoutRounding,而第二个在 Canvas 容器上使用 UseLayoutRounding(然后属性也继承到 Lines)。

      但是,这种差异会产生一些有趣的结果。当在容器上使用 UseLayoutRounding 时,单个像素线始终保持分布在 2 个像素上并且它们不会四处移动。当直接在线条上使用 UseLayoutRounding 并调整大小时,线条有时会锐利 1 个像素...而其他时候会超过 2 个像素。

      这让我想到了原始问题中的示例 xaml。上面有几个cmets:

      1. 首先,您应该意识到 UseLayoutRounding 和 SnapsToDevicePixels 属性都继承。也就是说,如果你在布局容器上使用它,它将继承到布局容器中的项目。
      2. UseLayoutRounding 和 SnapsToDevicePixels 不一定要一起使用。它们可以是……但我通常会尝试单独使用它们……其中一种。更多信息在这里:When should I use SnapsToDevicePixels in WPF 4.0?
      3. TextOptions.TextFormattingMode 选项影响文本,而不是行。
      4. 您用作布局容器的 StackPanel 也可能影响线的布局方式。 Canvas 允许您更精确地控制线条的定位。 StackPanel 只会在另一行之后布置一行......并且可能会产生一些意想不到的结果。

      比原始海报想要的更多信息。但是,我个人知道在 WPF 中使线条清晰是多么棘手。希望此信息对某人有所帮助!

      【讨论】:

        【解决方案3】:

        原因显然更简单。我只在“VB 2010 中的 Pro WPF”中找到了解释,但在 MSDN 上没有找到:http://books.google.de/books?id=F-gMZkAlUDUC&pg=PA334&lpg=PA334

        简而言之,StrokeThickness 将被分割为一个形状的两侧,因此 StrokeThickness 为 1 等于每侧的厚度为 0.5,由于线条只有一侧,因此它将是 0.5 个单位厚,因此即使使用SnapsToDevicePixels=True 也会显得模糊。因此,只需使用“2”作为 StrokeThickness。

        您可以通过使用 4 的 StrokeThickness 来验证这一点,那么线条的粗细将为 2,这不仅仅是“意外”的单个像素偏差。

        【讨论】:

        • 你最后一句话不准确。如果您将 StrokeThickness 设置为 4 ...它的描边粗细应该为 4 ...或者描边粗细应该为 3,在 3 个实心像素的两侧各有一个半像素。
        • @cplotts 为什么不准确?测试的时候有没有得到其他结果?
        • 绝对是@floele。我很想看看你所描述的一些示例代码。
        【解决方案4】:

        您是否尝试将 TextOptions.TextFormattingMode 属性更改为 Display ?详情请参阅 Lester Lobo 的this post

        【讨论】:

        • 试过了,对我没有任何改变。适合你吗?
        • 老实说,我没有尝试...我只记得莱斯特博客上的那篇文章;)
        • TextOptions.TextFormattingMode 在我的理解中应该只适用于文本。这不应该影响事情。但它在使文本看起来更好时非常有用!
        猜你喜欢
        • 2023-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-18
        相关资源
        最近更新 更多