我有一个非常简单的场景:有一个画布,我需要使用MouseMove在画布上画一条线。但是当我移动鼠标指针时,第二行的点(在鼠标移动中设置)与当前鼠标位置不匹配。
UPD 2:
Delta取决于鼠标的速度,如果速度很大 - delta很大且很明显(滞后)。我注意到如果你移动鼠标的速度不是很快而且速度不是很慢,这个bug会更明显
您可以下载示例项目here。
当鼠标快速移动时,图片上的内容就像:
一些源代码:
<Window x:Class="WpfApplication32.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Canvas x:Name="MainCanvas"
MouseLeftButtonDown="MainCanvas_OnMouseLeftButtonDown"
MouseMove="MainCanvas_OnMouseMove"
Background="White"
/>
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfApplication32
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Line _currentLine;
private bool _isDrawing;
public MainWindow()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
MainCanvas.Focus();
}
private void MainCanvas_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (_isDrawing)
{
_currentLine = null;
_isDrawing = false;
return;
}
_isDrawing = true;
_currentLine = new Line(){Stroke = Brushes.Green};
var p = e.GetPosition(MainCanvas);
_currentLine.X1 = p.X;
_currentLine.Y1 = p.Y;
_currentLine.X2 = p.X;
_currentLine.Y2 = p.Y;
MainCanvas.Children.Add(_currentLine);
}
private void MainCanvas_OnMouseMove(object sender, MouseEventArgs e)
{
if (_currentLine == null)
return;
var p = e.GetPosition(MainCanvas);
_currentLine.X2 = p.X;
_currentLine.Y2 = p.Y;
}
}
}
我已经尝试使用CompositeTarget.Render,也计时器每隔20ms改变第二个点,但它没有帮助。
我有遗留项目,代码在很大程度上依赖于这种方法(canvas mouseMove和shapes)。因此,我需要最简单的方法来消除这种滞后或关于此错误原因的一些想法)谢谢。
UPD: 我试图用这个问题录制视频,但我不擅长。这是我录制的一些屏幕来显示问题: http://prntscr.com/64hueg
UPD 2: 我试图使用OnRender of Window对象在没有画布的情况下做同样的事情。我已经使用DataContext绘制线 - 这里也是同样的问题。 DataContext被认为比Canvas和Line(Shape)更快。所以这不是Canvas问题。
我也尝试使用WritableBitmap绘制线 - 没有区别。
我认为MouseMove事件可能存在问题 - 我读过如果有很多对象(不是我的情况但仍然)MouseMove可能会因为延迟而触发,所以我使用了Win32 WM_MOUSEMOVE,但它也没有帮助。在我的情况下,MW_MOUSEMOVE和wpf MouseMove事件之间的延迟是<1000蜱。
到目前为止,我看到的唯一答案是渲染延迟。我不知道如何改进它,因为它是wpf internals =(。 顺便说一下,Paint.net似乎使用wpf,这个问题也出现在那里。
答案 0 :(得分:1)
这是无法修复的,因为这是由WPF的内部渲染系统引起的。即使视觉树很简单,总会有延迟。复杂的可视化树导致更多延迟。我花了很多时间来解决这个问题。
答案 1 :(得分:0)
请不要在主画布上而是在Window本身上使用MouseMove
事件。
我最近在MouseMove
上使用Image
时遇到了同样的问题,这很糟糕
切换到window的事件对我很有帮助。
<Window x:Name="Window1" x:Class="WpfApp2.MViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="MViewer" Height="454.411" Width="730.515" Loaded="Window_Loaded" Closing="Window1_Closing" ContentRendered="Window1_ContentRendered" MouseMove="Window1_MouseMove">
<Grid>
<Image x:Name="Image1" MouseMove="Image1_MouseMove"/>
<Line Name="Line1" Visibility="Visible" Stroke="Red" StrokeThickness="0.75" />
<Line Name="Line2" Visibility="Visible" Stroke="Red" StrokeThickness="0.75" />
</Grid>
</Window>
和
private void Window1_MouseMove(object sender, MouseEventArgs e)
{
Line1.Visibility = Visibility.Visible;
Line1.X1 = Mouse.GetPosition(this).X;
Line1.X2 = Mouse.GetPosition(this).X;
Line1.Y1 = 0;
Line1.Y2 = Window1.Height;
Line2.Visibility = Visibility.Visible;
Line2.X1 = 0;
Line2.X2 = Window1.Width;
Line2.Y1 = Mouse.GetPosition(this).Y;
Line2.Y2 = Mouse.GetPosition(this).Y;
}