Артефакты сглаживания в WPF

У меня странная проблема с рендерингом, когда я пытаюсь использовать сглаженную графику в WPF.

Вот упрощенная версия.

Если я использую следующий XAML

<Window x:Class = "RenderingBug.Window1" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "Window1" Width = "300" Height = "300">
    <Grid Name = "myGrid" Background = "AntiqueWhite" Width = "250" Height = "250">
        <ScrollViewer Name = "myScrollViewer" HorizontalScrollBarVisibility = "Auto" VerticalScrollBarVisibility = "Auto">
            <Canvas Height = "500" Width = "500" Name = "myCanvas" />
        </ScrollViewer>        
    </Grid>
 </Window>

И следующие cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace RenderingBug
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            PathFigureCollection pfc = new PathFigureCollection();
            PathFigure pf = new PathFigure();
            pf.StartPoint = new Point(100, 20);
            LineSegment ls = new LineSegment();
            ls.Point = new Point(20, 100);
            PathSegmentCollection psc = new PathSegmentCollection();
            psc.Add(ls);
            pf.Segments = psc;
            pfc.Add(pf);
            PathGeometry pg = new PathGeometry(pfc);

            RectangleGeometry clippingRectangle = new RectangleGeometry(new Rect(0, 0, 80, 80));

            Path p1 = new Path();
            p1.ClipToBounds = true;
            p1.Clip = clippingRectangle;
            p1.StrokeDashCap = PenLineCap.Square;
            p1.Stroke = Brushes.Black;
            p1.StrokeThickness = 30;
            p1.Data = pg;
            myCanvas.Children.Add(p1);

            Path p2 = new Path();
            p2.ClipToBounds = true;
            p2.Clip = clippingRectangle;
            p2.StrokeDashCap = PenLineCap.Square;
            p2.Stroke = Brushes.White;
            p2.StrokeThickness = 10;
            p2.Data = pg;
            myCanvas.Children.Add(p2);
        }
    }
}

У меня возникает странная проблема с рендерингом со сглаживанием, где находится край прямоугольника обрезки (при запуске программы это будет довольно очевидно, но это туманная серая линия, где прямоугольник обрезки обрезает пути).

Я пробовал различные методы, такие как выравнивание элементов управления по определенным пикселям и установка SnapsToDevicePixels для различных элементов управления в надежде, что это решит эту проблему (удалите дополнительную туманную серую полосу), но, похоже, ничего не помогает.

Любые идеи?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
3 637
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Оказывается, это потому, что, хотя окно, конечно, выровнено по границе пикселя, сетка внутри окна может не быть. Исправить это не слишком сложно, но может потребоваться время, чтобы понять, что делать.

Есть хорошая функция SnapsToDevicePixels, которая должна правильно все выровнять. И, к сожалению, по какой-то причине он, похоже, вообще не работает (кажется, это понятная ошибка). Так что делать?

Во-первых, сетка должна быть выровнена по границе пикселей (то есть не по центру или что-то в этом роде, поскольку, если окно имеет нечетное количество пикселей в горизонтальном или вертикальном направлении, то сетка и, следовательно, содержимое сетки будут смещены. .)

Но есть и другие проблемы, с которыми нужно иметь дело ... как только вы начинаете прокручивать полосы прокрутки, артефакт появляется снова! Это связано с тем, что полосы прокрутки не обязательно прокручивают содержимое на целое число пикселей. Чтобы справиться с этим, я фиксирую некоторые события в ScrollViewer, чтобы установить для места прокрутки целочисленные значения.

private void workingAreaScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
{
    double w = e.NewSize.Width;
    double h = e.NewSize.Height;
    workingAreaScrollViewer.Width = Math.Round(w);
    workingAreaScrollViewer.Height = Math.Round(h);
}

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.A)
    {
        workingAreaCanvas.Children.Remove(p2);
    }
    if (e.Key == Key.Z && p2.Parent != workingAreaCanvas)
    {
        workingAreaCanvas.Children.Add(p2);
    }
}

Сделай это, и, кажется, все будет хорошо.

(В качестве примечания для людей, у которых возникают проблемы с изображением внутри ScrollViews ... если вы столкнулись с той же проблемой, это также должно исправить это, если изображение не масштабируется, не поворачивается и т. д. пока вы просто пытаетесь выровнять изображение по границе пикселей, это должно сработать.)

Другие вопросы по теме