Как можно избежать сглаживания с помощью WPF? - PullRequest
4 голосов
/ 17 декабря 2009

Одна из больших проблем с WPF - это сглаживание. Фактически, именно поэтому UseLayoutRending был представлен в WPF 4.0. Тем не менее, это не работает для меня в следующем примере:

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

Ответы [ 4 ]

2 голосов
/ 15 декабря 2014

Получение четких линий в 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>

Единственное различие между двумя фрагментами заключается в том, что первый использует UseLayoutRounding для строк, а второй использует UseLayoutRounding для контейнера Canvas (который затем также наследует свойство для строк).

Однако эта разница дает некоторые интересные результаты. Когда UseLayoutRounding используется в контейнере, отдельные пиксельные линии постоянно остаются растянутыми на 2 пикселя, и они не перемещаются. Когда UseLayoutRounding используется на линиях напрямую, и вы изменяете размер, линии иногда будут иметь резкость 1 пиксель ... а в других случаях будет превышать 2 пикселя.

И это подводит меня к примеру xaml в оригинальном вопросе. Несколько комментариев по этому поводу:

  1. Прежде всего, вы должны понимать, что оба свойства UseLayoutRounding и SnapsToDevicePixels наследуются. То есть, если вы используете его в контейнере макета, он наследует элементы в контейнере макета.
  2. UseLayoutRounding и SnapsToDevicePixels не обязательно должны использоваться вместе. Они могут быть ... но я обычно пытаюсь использовать их по отдельности ... либо один, либо другой. Более подробная информация здесь: Когда мне следует использовать SnapsToDevicePixels в WPF 4.0?
  3. Параметры TextOptions.TextFormattingMode влияют на текст, а не на строки.
  4. Эта StackPanel, которую вы используете в качестве контейнера макета, также может влиять на расположение линий. Canvas позволяет более точно управлять позициями ваших линий. StackPanel просто разместит одну строку за другой ... и может привести к неожиданным результатам.

Больше информации, чем хотел оригинальный плакат. Тем не менее, я лично знаю, как сложно получить четкие линии в WPF. Надеюсь, эта информация кому-нибудь поможет!

2 голосов
/ 15 марта 2013

Ответ Фоеле показал правильное направление, но ответ не был полным. Просто установите значения y равными половине пикселя, например, Y1 = "7" -> Y1 = "7,5"

Вот почему вторая и третья строки не размыты.

1 голос
/ 02 января 2012

Причина, по-видимому, проще. Я нашел объяснение только в «Pro WPF в 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.

Вы можете проверить это с помощью StrokeThickness из 4, тогда толщина линии будет равна 2, что превышает «случайное» отклонение в один пиксель.

0 голосов
/ 17 декабря 2009

Вы пытались изменить свойство TextOptions.TextFormattingMode на Display? См. этот пост от Lester Lobo для деталей

...