博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF使用Canvas绘制可变矩形
阅读量:4554 次
发布时间:2019-06-08

本文共 5015 字,大约阅读时间需要 16 分钟。

1、问题以及解决办法

最近因为项目需要,需要实现一个位置校对的功能,大致的需求如下:有一个图片,有一些位置信息,但是位置信息可能和实际有些偏差,需要做简单调整,后面会对这张图片进行切割等,做些处理。(位置信息连接起来是一个个小矩形。)

解决以上问题的大致思路如下:使用canvas进行绘制,把图片作为canvas的背景,在canvas上绘制矩形,类似于qq截图一样,矩形框可以使用鼠标拖动调整大小。然后在记下修改后的位置,提供给后面切割图片使用。目前的关键问题就是实现类似qq截图那样可以拖动的矩形

2、实现的效果预览

以上是实现的demo的效果。主要由定位点和连线组成。

3、可变矩形实现

  1. 定位点
    定位点主要用于描述在矩形上的小方框,鼠标拖动的事件就是由它触发,它位置的移动会联动相关线的移动。

定位点主要是定位点的一些基本属性和基本方法,主要包括绘制方法,移动方法。

其中:AnchorPointType为定位点的类型;

public enum AnchorPointType    {        ///         /// 上下        ///         NS,        ///         /// 左右        ///         WE,        ///         /// 右上        ///         NE,        ///         /// 左下        ///         SW,        ///         /// 右下        ///         NW,        ///         /// 左上        ///         SE    }

draw()方法用于绘制矩形:

public Rectangle Draw()         {            double offset = this.Width / 2;            Rectangle retc = new Rectangle()            {                Margin = new Thickness(this.X - offset, this.Y - offset, 0, 0),                Width = this.Width,                Height = this.Height,                Fill = Brushes.LightGoldenrodYellow,                Stroke = Brushes.Black,                StrokeThickness = 1,                DataContext = this.Key            };            this.retc = retc;            return retc;        }

move()方法用户改变定位点位置

public void Move(double x,double y)        {            double offset = this.Width / 2;            this.retc.Margin = new Thickness(x-offset,y-offset,0,0);            this.X = x;            this.Y = y;        }
  1. 可变矩形
    这部分主要实现绘制矩形功能,主要代码如下:
    public void Init()     {         //按x轴分类         IEnumerable
    > pointXs = points.GroupBy(o => o.X); //按y周分类 IEnumerable
    > pointYs = points.GroupBy(o => o.Y); //绘制竖线 DrawXLine(pointXs); //绘制横线 DrawYLine(pointYs); //设置定位点 AddAnchorPoints(); //绘制定位点并且添加事件 foreach (AnchorPoint anchorPoint in anchorPoints) { Rectangle rec=anchorPoint.Draw(); rec.MouseLeftButtonDown += new MouseButtonEventHandler(rec_MouseLeftButtonDown); rec.MouseMove += new MouseEventHandler(rec_MouseMove); canvas.Children.Add(rec); } //canvas添加事件 canvas.MouseLeftButtonUp += new MouseButtonEventHandler(canvas_MouseLeftButtonUp); canvas.MouseMove += new MouseEventHandler(canvas_MouseMove); canvas.MouseLeave += new MouseEventHandler(canvas_MouseLeave); }
    如上代码:
    如上代码:
    1、按x轴,y轴分类
    2、绘制竖线,横线
    3、设置定位点
    4、绘制定位点并且添加事件监听
    5、给canvas添加事件
    给每个定位点添加鼠标MouseMove和MouseLeftButtonDown事件,给canvas添加MouseMove,MouseLeave,MouseLeftButtonUp事件。
    具体代码不在粘贴了,如果需要代码,可以去下载源代码
  2. 矩形线联动
    矩形线联动,主要是以点带线,通过判断线是否和动点相关联,联动相关的线。主要代码如下:
    private void MoveLines(double x, double y)     {         List
    moveLines = new List
    (); moveLines = lines.Where(o => o.Y1 == curAnchorPoint.Y || o.Y2 == curAnchorPoint.Y || o.X1 == curAnchorPoint.X || o.X2 == curAnchorPoint.X).ToList(); foreach (Line line in moveLines) { if (line.Y1 == curAnchorPoint.Y) { line.Y1 = y; } if (line.Y2 == curAnchorPoint.Y) { line.Y2 = y; } if (line.X1 == curAnchorPoint.X) { line.X1 = x; } if (line.X2 == curAnchorPoint.X) { line.X2 = x; } } }
  3. 定位点联动

点的联动,和线的联动方法类似,但是点的联动要比线的联动复杂,主要在以下三个方面:1、点的移动需要联动中点的联动。2、在矩形的四个顶点变动时,需要联动其他两个相邻的顶点,和相邻两条线的中点的联动。3、不同的方向点的联动,不一样,会有很多if else。

由于代码较长,就不粘贴了,需要源代码可以去获取源代码。
线中点联动:线的中点联动需要考虑,移动的点是否关联到计算这个中点的两个点或者一个点,关联到中点的这两个点如果有改变,则这个中点就需要改变。主要代码如下:

private void MoveRefAnchorPoint(double x, double y,AnchorPoint movedAnchorPoint)        {            foreach (AnchorPoint anchorPoint in anchorPoints)            {                if (anchorPoint.RefPoint.Length == 2)                {                    if (anchorPoint.RefPoint[0].X == x && anchorPoint.RefPoint[0].Y == y)                    {                        anchorPoint.RefPoint[0].X = movedAnchorPoint.X;                        anchorPoint.RefPoint[0].Y = movedAnchorPoint.Y;                    }                    else if (anchorPoint.RefPoint[1].X == x && anchorPoint.RefPoint[1].Y == y)                    {                        anchorPoint.RefPoint[1].X = movedAnchorPoint.X;                        anchorPoint.RefPoint[1].Y = movedAnchorPoint.Y;                    }                    anchorPoint.X = (anchorPoint.RefPoint[0].X + anchorPoint.RefPoint[1].X) / 2;                    anchorPoint.Y = (anchorPoint.RefPoint[0].Y + anchorPoint.RefPoint[1].Y) / 2;                    anchorPoint.Move();                }            }        }

以上为单个关联点改变的情况的代码,两个关联点都变动的代码和这个类似。

4、获取源代码

由于文字表达能力有限,另外说清点和线的关系,特别是点和线的联动,确实有点困难,如果感兴趣的话,强烈建议下载代码进行调试阅读。

转载于:https://www.cnblogs.com/JerryWang1991/p/3936386.html

你可能感兴趣的文章
mysql提示Column count doesn't match value count at row 1错误
查看>>
前端--jstree--异步加载数据
查看>>
CSS定位深入理解 完全掌握CSS定位 相对定位和绝对定位
查看>>
网络体系结构
查看>>
练习4.13、4.14、4.15、4.16
查看>>
SAP库龄表
查看>>
PhantomJS 基础及示例 (转)
查看>>
20175316盛茂淞 2018-2019-2 《Java程序设计》第3周学习总结
查看>>
zookeeper安装
查看>>
js清空页面控件值
查看>>
Appium使用Python运行appium测试的实例
查看>>
django request bug
查看>>
二叉树_非递归先中后序_递归非递归求深度
查看>>
20181227 新的目标
查看>>
HDFS写流程
查看>>
生产环境服务器环境搭建+ 项目发布
查看>>
js按条件分类json数组,并合计同组数据(一维转换为二维)
查看>>
Exp6 信息搜集与漏洞扫描
查看>>
redis4安装
查看>>
使用命令wsimport构建WebService客户端[转]
查看>>