您的位置:首页 > 其它

WPF:使用鼠标在Canvas面板上画线

2015-09-08 15:13 567 查看

使用Canvas+Line 任意画线

主要使用布局面板Canvas作为背景,通过其属性Children添加Line 来实现画线。可以理解为 每一个Line 就是一个点。
不清楚Canvas的用法可以参见:点击打开链接 Line的参见:点击打开链接

操作效果



按下鼠标左键任意画线,可以修改线的颜色(红色,绿色)修改线的样式(实线,虚线)。后期增加导出生成图片功能。

代码解析

线由点组成,当然我这里的点其实就是线。线由开始点与结束点构成,想必看到过msdn上line的解释就会一目了然。至于鼠标事件,会有鼠标左键按下以及移动,松开动作。 还需要有个一集合来存放点,取名为List<Point> 类型。 在鼠标按下事件中可以这样写:
/// <summary>
/// 起始位置
/// </summary>
Point startPoint;
/// <summary>
/// 点集合
/// </summary>
List<Point> pointList = new List<Point>();
/// <summary>
/// 鼠标左键按下获取开始Point
/// </summary>
private void Canvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
startPoint = e.GetPosition(myCanvas);
}
记录开始位置startPoint 。按下之后随之的就是Move动作,在移动事件中这样写:

/// <summary>
/// 按下鼠标左键移动
/// </summary>
private void Canvas_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
// 返回指针相对于Canvas的位置
Point point = e.GetPosition(myCanvas);

if (pointList.Count == 0)
{
// 加入起始点
pointList.Add(new Point(this.startPoint.X, this.startPoint.Y));
}
else
{
// 加入移动过程中的point
pointList.Add(point);
}

// 去重复点
var disList = pointList.Distinct().ToList();
var count = disList.Count(); // 总点数
if (point != this.startPoint && this.startPoint != null)
{
var l = new Line();
string color = (cboColor.SelectedItem as ComboBoxItem).Content as string;

if (color == "默认")
{
l.Stroke = Brushes.Black;
}
if (color == "红色")
{
l.Stroke = Brushes.Red;
}
if (color == "绿色")
{
l.Stroke = Brushes.Green;
}
l.StrokeThickness = 1;
if (count < 2)
return;
l.X1 = disList[count - 2].X;  // count-2  保证 line的起始点为点集合中的倒数第二个点。
l.Y1 = disList[count - 2].Y;
// 终点X,Y 为当前point的X,Y
l.X2 = point.X;
l.Y2 = point.Y;
myCanvas.Children.Add(l);
}
}
}


移动过程中创建Line对象并加入Canvas中。 代码中的颜色判断最好修改成枚举类型。

修改线颜色及样式

这部分比较简单,直接遍历Canvas中的Line对象,修改Line的Stroke属性,StrokeDashArray属性。

/// <summary>
/// 选择颜色
/// </summary>
private void cboColor_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string color = (cboColor.SelectedItem as ComboBoxItem).Content as string;
if (this.myCanvas != null)
{

List<Line> list = GetChildObjects<Line>(this.myCanvas);
if (list.Count > 0)
{
list.ForEach(l =>
{
if (color == "默认")
{
l.Stroke = Brushes.Black;
}
if (color == "红色")
{
l.Stroke = Brushes.Red;
}
if (color == "绿色")
{
l.Stroke = Brushes.Green;
}
});
list.Clear();
}
}
}


/// <summary>
/// 选择style
/// </summary>
private void cboStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string style = (cboStyle.SelectedItem as ComboBoxItem).Content as string;
if (this.myCanvas == null)
{
return;
}
List<Line> list = GetChildObjects<Line>(this.myCanvas);
if (list.Count > 0)
{
list.ForEach(l =>
{
if (style == "默认")
{
l.StrokeDashArray = new DoubleCollection(new List<double>() { });
}
if (style == "虚线")
{
l.StrokeDashArray = new DoubleCollection(new List<double>() {
1,1,1,1
});
}
});
list.Clear();
}
}


GetChildObjects 方法参见博客文章。

前台XAML

主要用到了WrapPanel,StackPanel布局控件。

<WrapPanel>
<StackPanel>
<WrapPanel>
<Label Content="颜色:" VerticalAlignment="Center"></Label>
<ComboBox x:Name="cboColor" SelectedIndex="0" Width="120" Margin="10" SelectionChanged="cboColor_SelectionChanged">
<ComboBoxItem>默认</ComboBoxItem>
<ComboBoxItem>红色</ComboBoxItem>
<ComboBoxItem>绿色</ComboBoxItem>
</ComboBox>
</WrapPanel>
<WrapPanel>
<Label Content="样式:" VerticalAlignment="Center"></Label>
<ComboBox x:Name="cboStyle" Width="120" Margin="10" SelectionChanged="cboStyle_SelectionChanged">
<ComboBoxItem IsSelected="True">默认</ComboBoxItem>
<ComboBoxItem>虚线</ComboBoxItem>
</ComboBox>
</WrapPanel>
</StackPanel>
<Canvas Width="500" Height="500" Background="Gray" x:Name="myCanvas" PreviewMouseLeftButtonDown="Canvas_PreviewMouseLeftButtonDown" PreviewMouseMove="Canvas_PreviewMouseMove">
</Canvas>
</WrapPanel>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: