如何避免 WPF 抗锯齿?

发布于 2024-08-14 19:40:28 字数 1064 浏览 2 评论 0原文

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测试版的一个bug?

One of the big problems with WPF is anti aliasing.
In fact, that's why UseLayoutRending was introduced in WPF 4.0.
However, it does not work for me in the following sample:

<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>

The last two lines are still blurry.
(I am using Windows 7)

Any solution?

Or is it a bug in the beta of WPF 4.0?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

别理我 2024-08-21 19:40:29

在 WPF 中让线条看起来清晰可能相当困难!有时......似乎也需要一点黑魔法!

我认为弗洛埃和金克的答案指向了正确的方向。也就是说,很多时候您会希望将单像素线放在 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>

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

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

这让我想到了原始问题中的示例 xaml。对此的一些评论:

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

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

Getting lines to look sharp in WPF can be quite hard! And some times ... it seems like it takes a bit of black magic too!

I think that floele and Kimke's answers are pointing in correct direction. That is, often times you will want to put single pixel lines on a 0.5 pixel boundary ... given the way that it draws the line (half on one side and half on another).

However, it isn't always that simple either. For example, it also depends on the surrounding xaml. For example, try this code out and resize when you do:

<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>

Then, try this code out (again, resize when you do):

<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>

The only difference between the two snippets is that the first uses UseLayoutRounding on the Lines while the second uses UseLayoutRounding on the Canvas container (which then also property inherit to the Lines).

However, that difference yields some interesting results. When UseLayoutRounding is used on the container the single pixel lines consistently stay spread out over 2 pixels and they don't move around. When UseLayoutRounding is used on the Lines directly, and you resize, the lines will sometimes be 1 pixel sharp ... and other times will be spead over 2 pixels.

And that brings me to the sample xaml in the original question. A few comments on it:

  1. First off, you should realize that both UseLayoutRounding and SnapsToDevicePixels property inherit. That is, if you use it on the layout container it will inherit to the items in the layout container.
  2. UseLayoutRounding and SnapsToDevicePixels shouldn't necessarily be used together. They can be ... but I would normally try using them separately ... either one or the other. More info here: When should I use SnapsToDevicePixels in WPF 4.0?
  3. TextOptions.TextFormattingMode options affect text, not lines.
  4. That StackPanel that you are using as the layout container could also affect how the lines are being laid out. Canvas allows you more precise positioning control of your lines. StackPanel will just layout one line after the other line ... and might yield some unexpected results.

More info than what the original poster was wanting. However, I personally know how tricky it is to get lines sharp in WPF. Hope this info helps someone!

晨敛清荷 2024-08-21 19:40:29

原因显然更简单。我只在“Pro WPF in VB 2010”中找到了解释,但在 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,这不仅仅是“偶然”的单像素偏差。

The reason is apparently simpler. I only found an explanation in "Pro WPF in VB 2010" and not on MSDN though: http://books.google.de/books?id=F-gMZkAlUDUC&pg=PA334&lpg=PA334

In short, the StrokeThickness will be divided for both sides of a shape, so a StrokeThickness of 1 equals a thickness of 0.5 for each side, and since the line only has one side, it will be 0.5 units thick and thus appear blurry even when using SnapsToDevicePixels=True. So simply use "2" as StrokeThickness.

You can verify this by using a StrokeThickness of 4, the line will have a thickness of 2 then, which is more than an "accidential" single pixel deviation.

娜些时光,永不杰束 2024-08-21 19:40:29

您是否尝试将 TextOptions.TextFormattingMode 属性更改为 Display ?请参阅此内容Lester Lobo 发布的帖子了解详细信息

Have you tried to change the TextOptions.TextFormattingMode property to Display ? See this post from Lester Lobo for details

辞取 2024-08-21 19:40:28

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

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

Floele's answer showed the right direction, but the answer was not complete. Just set the y-values to half a pixel, e.g. Y1="7" -> Y1="7.5"

That's the reason the second and third lines are not blurred.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文