以编程方式为 WPF InkCanvas 创建 Strokes 的性能问题
Performance problem of creating Strokes for an WPF InkCanvas programmatically
我在 Cancel touch event on InkCanvas (.Net Framework) 中问了一个问题但没有得到答案,所以我尝试将 InkCanvas
设置为 HitTestVisible
到 false
并获得 StylusPoints
在 driver 的 API 之上。这些点现在被手动放入 Stroke
s 中,然后放入边界 StrokeCollection
中。这样,我只从手写笔而不是触摸或鼠标获得点数(我知道 UWP InkCanvas
默认情况下可以做到这一点,但遗憾的是 WPF 太旧了,没有得到 Microsoft 的正确支持)。
但是我对这种方法的速度有疑问。我从每个点(以及之前的点)中提取出 Stroke
,并将它们放在 StrokeCollection
中。这导致“缓慢”Stroke
。如果我写了一些东西,当我已经用笔完成它时,它只会显示大约 3/4,然后在半秒后完全显示。您是否有任何想法可以使它更快,使其看起来像 InkCanvas
的正常使用?或者可以回答之前的问题 ;)
这是我的代码:
private void TabLib_DataReceived(object sender, EventArgs e)
{
float pressureFactor = e.pressure / 1024f;
StylusPoint newPoint = new StylusPoint()
{
PressureFactor = pressureFactor,
X = e.xPos,
Y = e.yPos
};
if (pressureFactor == 0) // that means the pen has left or entered the tablet
{
_oldPressurePoint = newPoint;
return;
}
StylusPointCollection pointList = new StylusPointCollection();
pointList.Add(_oldPressurePoint);
pointList.Add(newPoint);
Stroke stroke = new Stroke(pointList, _penDrawingAttributes);
// used a dispatcher begininvoke because of DrawnStrokes are bound to the UI thread.
_tabletWindow.Dispatcher.BeginInvoke(new Action<Stroke>((newStroke) =>
{
DrawnStrokes.Add(newStroke); // DrawnStrokes is the bound StrokeCollection
}), stroke);
_oldPressurePoint = newPoint;
}
我也想过画一笔,只加点,但是好像不行。如果你已经添加了一个笔画,你就不能在这个笔画上加点了,可以吗?
只在必要时创建新的Stroke,并在当前Stroke的StylusPoints集合中添加点。
这是一个流畅运行的示例,它根据鼠标输入在 Canvas 覆盖 InkCanvas 上创建笔画数据Canvas。
<Grid>
<InkCanvas x:Name="inkCanvas" IsHitTestVisible="False"/>
<Canvas Background="Transparent"
MouseLeftButtonDown="CanvasMouseLeftButtonDown"
MouseLeftButtonUp="CanvasMouseLeftButtonUp"
MouseMove="CanvasMouseMove"/>
</Grid>
后面有这段代码:
private Stroke stroke;
private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var pos = e.GetPosition(inkCanvas);
var points = new StylusPointCollection
{
new StylusPoint(pos.X, pos.Y)
};
stroke = new Stroke(points, inkCanvas.DefaultDrawingAttributes);
inkCanvas.Strokes.Add(stroke);
}
private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
stroke = null;
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
if (stroke != null)
{
var pos = e.GetPosition(inkCanvas);
stroke.StylusPoints.Add(new StylusPoint(pos.X, pos.Y));
}
}
我在 Cancel touch event on InkCanvas (.Net Framework) 中问了一个问题但没有得到答案,所以我尝试将 InkCanvas
设置为 HitTestVisible
到 false
并获得 StylusPoints
在 driver 的 API 之上。这些点现在被手动放入 Stroke
s 中,然后放入边界 StrokeCollection
中。这样,我只从手写笔而不是触摸或鼠标获得点数(我知道 UWP InkCanvas
默认情况下可以做到这一点,但遗憾的是 WPF 太旧了,没有得到 Microsoft 的正确支持)。
但是我对这种方法的速度有疑问。我从每个点(以及之前的点)中提取出 Stroke
,并将它们放在 StrokeCollection
中。这导致“缓慢”Stroke
。如果我写了一些东西,当我已经用笔完成它时,它只会显示大约 3/4,然后在半秒后完全显示。您是否有任何想法可以使它更快,使其看起来像 InkCanvas
的正常使用?或者可以回答之前的问题 ;)
这是我的代码:
private void TabLib_DataReceived(object sender, EventArgs e)
{
float pressureFactor = e.pressure / 1024f;
StylusPoint newPoint = new StylusPoint()
{
PressureFactor = pressureFactor,
X = e.xPos,
Y = e.yPos
};
if (pressureFactor == 0) // that means the pen has left or entered the tablet
{
_oldPressurePoint = newPoint;
return;
}
StylusPointCollection pointList = new StylusPointCollection();
pointList.Add(_oldPressurePoint);
pointList.Add(newPoint);
Stroke stroke = new Stroke(pointList, _penDrawingAttributes);
// used a dispatcher begininvoke because of DrawnStrokes are bound to the UI thread.
_tabletWindow.Dispatcher.BeginInvoke(new Action<Stroke>((newStroke) =>
{
DrawnStrokes.Add(newStroke); // DrawnStrokes is the bound StrokeCollection
}), stroke);
_oldPressurePoint = newPoint;
}
我也想过画一笔,只加点,但是好像不行。如果你已经添加了一个笔画,你就不能在这个笔画上加点了,可以吗?
只在必要时创建新的Stroke,并在当前Stroke的StylusPoints集合中添加点。
这是一个流畅运行的示例,它根据鼠标输入在 Canvas 覆盖 InkCanvas 上创建笔画数据Canvas。
<Grid>
<InkCanvas x:Name="inkCanvas" IsHitTestVisible="False"/>
<Canvas Background="Transparent"
MouseLeftButtonDown="CanvasMouseLeftButtonDown"
MouseLeftButtonUp="CanvasMouseLeftButtonUp"
MouseMove="CanvasMouseMove"/>
</Grid>
后面有这段代码:
private Stroke stroke;
private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var pos = e.GetPosition(inkCanvas);
var points = new StylusPointCollection
{
new StylusPoint(pos.X, pos.Y)
};
stroke = new Stroke(points, inkCanvas.DefaultDrawingAttributes);
inkCanvas.Strokes.Add(stroke);
}
private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
stroke = null;
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
if (stroke != null)
{
var pos = e.GetPosition(inkCanvas);
stroke.StylusPoints.Add(new StylusPoint(pos.X, pos.Y));
}
}