用鼠标移动绘制的线

2023-12-03

我试图通过用鼠标抓住一条绘制的线来移动它。

这条线已经画好了Graphics.DrawLine(Pen P, Point A, Point B).

创建线条并将其绘制在表单上绝对没有问题。

我试过了:

  • 将行添加到GraphicsPath- 这甚至没有划清界限OnPaint.

  • 检查是否MouseEventArgs e.Location与一些基本代数有关(到目前为止我已经放弃了计算)

总结一下:我想抓住线路并将其拖动到某个地方,但我什至无法检查 e.Location 是否在线上,我该怎么做?

编辑:这就是我使用 GraphicsPath 时代码的样子。

当我不使用 GraphicsPath 时,我有:

if (s.thisShape == ShapeType.Line) {
  g.DrawLine(pen, s.p1, s.p2);
} else { ... }`

在 DrawingShapes 方法中。

从 drawStuff : Usercontrol 类:

private void drawStuff_MouseDown(object sender, MouseEventArgs e)
{
  pointRegion = e.Location;
  for (int i = 0; i < Shapes.Count; i++)
  {
    if (Shapes[i].Region.IsVisible(pointRegion))
    {
      isDragging = true;
      count = i;
      break;
    }
  }
}

private void drawStuff_MouseMove(object sender, MouseEventArgs e)
{
  if (isDragging)
  {
    Shapes[count].moveWithDiff(pointRegion, e.Location);
    pointRegion = e.Location;
    Refresh();
  }
}

private void drawStuff_MouseUp(object sender, MouseEventArgs e)
{
  isDragging = false;
  Refresh();
}

protected override void OnPaint(PaintEventArgs e)
{
  base.OnPaint(e);
  drawShapes(e.Graphics);
}

private void drawShapes(Graphics g)
{
  temporaryPen = pennaLeft;
  foreach (Shape s in Shapes)
  {
    g.FillRegion(temporaryPen, s.Region);
  }
}

从 Shape : Usercontrol 类:

public void moveWithDiff(Point pr, Point mp)
{
  Point p = new Point();
  if (this.thisShape == ShapeType.Line)
  {
    p.X = mp.X - pr.X;
    p.Y = mp.Y - pr.Y;
    this.p1.X += p.X;
    this.p1.Y += p.Y;
    this.p2.X += p.X;
    this.p2.Y += p.Y;
  }
  RefreshPath();
}

private void RefreshPath()
{
  gPath = new GraphicsPath();
  switch (thisShape)
  {
    case ShapeType.Line:
      gPath.AddLine(this.p1, this.p2);
      break;
  }
  this.Region = new Region(gPath);
}

现在,这甚至没有画线,但是使用 DrawingShapes() 中的 if 语句它可以完美绘制,但我无法将其拖动到其他地方。


让我们从基础知识开始,在屏幕上画一条线。我创建了一个自定义类来处理我希望在此过程中可用的一些功能:

public class MyLine
{
    public Pen pen { get; set; }
    public Point Start { get; set; }
    public Point End { get; set; }

    public MyLine(Pen p, Point p1, Point p2)
    {
        pen = p;
        Start = p1;
        End = p2;
    }

    public float slope
    {
        get
        {
            return (((float)End.Y - (float)Start.Y) / ((float)End.X - (float)Start.X));
        }
    }
    public float YIntercept
    {
        get
        {
            return Start.Y - slope*Start.X;
        }
    }

    public bool IsPointOnLine(Point p, int cushion)
    {
        float temp = (slope * p.X + YIntercept);
        if (temp >= (p.Y-cushion) && temp <=(p.Y+cushion))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

这个类提供了一些帮助函数,可以让我们的生活更轻松。我们有返回斜率和 Y 截距的属性,因此我们可以确定某个点是否在线上。然后,我们提供一个辅助函数 IsPointOnLine(),它接受一个点和一个缓冲。缓冲垫用于简单地允许用户在距离线足够近的地方单击以使其返回 true。

接下来我将实例化这条线并在窗体的绘制事件中绘制它:

MyLine m;

private void Form1_Load(object sender, EventArgs e)
{
    m= new MyLine(Pens.Black, new Point(20, 20), new Point(40, 40));
}



private void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawLine(m.pen, m.Start, m.End);     
}

现在您应该能够运行您的应用程序并在屏幕上看到一条从 20,20 到 40,40 的行。

现在我想处理鼠标与线的交互,因此在 MouseDown 上,我们将查看单击点是否与线相交,以及是否设置了标志并保持与端点的增量。在 MouseMove 事件中,我们将查看该线是否已被单击但未释放,并相应地重置坐标。在 MouseUp 事件中,我们简单地重置我们的标志:

Point deltaStart;
Point deltaEnd;
bool dragging = false;

private void Form1_MouseDown(object sender, MouseEventArgs e)
{

    if (e.Button == System.Windows.Forms.MouseButtons.Left && m.IsPointOnLine(e.Location, 5))
    {
        dragging = true;
        deltaStart = new Point(m.Start.X - e.Location.X, m.Start.Y - e.Location.Y);
        deltaEnd = new Point(m.End.X - e.Location.X, m.End.Y - e.Location.Y);
    }
}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    if (dragging && deltaStart != null && deltaEnd != null )
    {
        m.Start = new Point(deltaStart.X + e.Location.X, deltaStart.Y + e.Location.Y);
        m.End = new Point(deltaEnd.X + e.Location.X, deltaEnd.Y + e.Location.Y);
        this.Refresh();
    }
}

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    dragging = false;
}

现在您应该能够在该线的 5 个像素范围内单击并使其随鼠标移动。

请注意,代码中的某些位置需要额外的错误处理,尤其是处理除 0 错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用鼠标移动绘制的线 的相关文章

随机推荐

  • 使用回调将 C 库 (GSL) 包装在 cython 代码中

    我是新手cython and c 我想使用 cython 来加快代码的性能 我想用gsl integration我的代码中的库用于集成 更新 test gsl pyx cdef extern from math h double log d
  • 如何在Android中每分钟获取gps坐标?

    我想每分钟获取我的坐标 即使用户没有移动 所以我使用 requestLocationUpdates 和以下参数 locMgr requestLocationUpdates LocationManager GPS PROVIDER 60000
  • NSMutableArray 内的块泄漏 (ARC)

    我有一些在块内的操作 此操作 仅更新一个UIImage像这样 UIImage image self myImage image 我的图像是通过访问互联网来计算的NSURLConnection 当我从互联网上收到图像时 我称该块为NSMuta
  • 如何优化在 postgresql 中查询这些数据?

    我的查询对于特定行来说速度很慢 Postgres 选择做一个Seq Scan而不是使用Index Scan对于某些行 我认为是因为它实际上比使用索引更快 以下是针对正常工作负载使用索引的查询计划 http explain depesz co
  • 高效构建FEM/FVM矩阵

    这是 FEM FVM 方程系统的典型用例 因此可能会引起更广泛的兴趣 从三角形网格 la 我想创建一个scipy sparse csr matrix 矩阵行 列表示网格节点处的值 该矩阵在主对角线上以及两个节点通过边连接的地方都有条目 这是
  • 本地化 MPMoviePlayerViewController 的“完成”按钮

    我正在使用 MPMoviePlayerViewController 来呈现视频 一切都按预期工作 但如果我将设备的语言切换为例如德语 完成 按钮未本地化 我尝试访问该按钮并将其设置为我自己的按钮实现 如下所示 MPMoviePlayerVi
  • 使 openGL 线连接起来

    现在我创建了一个多边形 然后我做了同样的事情 但使用 line loop 来绘制轮廓 我现在的问题是 如果我将线条粗细设置为高 则线条不会连接 它们的末端需要更长 线宽 有没有办法解决这个问题 Thanks glMatrixMode GL
  • Rails 条件验证

    所以我这里有两个模型 class Screen lt ActiveRecord Base belongs to user validates screen size numericality gt less than or equal to
  • 在 c 可执行文件中运行数据 shellcode

    我正在研究这个c 程序 我在 64 位 x64 linux 上用 gcc 编译它 include
  • 新的 React Context API 是否会触发重新渲染?

    我一直在尝试理解新的 React Context API 并正在使用它 我只是想检查一个简单的情况 当提供者的数据更新时 所有内容都会重新呈现 Check Codesandbox 上的这个小例子 所以 在我的例子中 我有一个App组件 具有
  • Paypal 支付 REST API Web 体验配置文件

    我正在使用 PayPal Rest API 并将 PayPal 与付款集成 我设法使用以下代码创建网络体验配置文件 但我无法运行此代码 2 次 它表示该配置文件已存在 这是否意味着我必须创建一个配置文件并将其用于所有客户和所有交易 Web
  • hbase 扫描仪的排序结果

    如何以相同的任何排序顺序检索 hbase 列族 值 like列族 值 列 1 1列 3 2列 4 3列 2 4 HBase 本身不会这样做 相反 您可以使用 Result raw 1 方法检索 KeyValues 列表 将其放入 List
  • F# 匹配两个值

    我对 F 相当陌生 我想使用 match with 语法比较两个值 当我尝试比较两个值时 问题就出现了 如下所示 let value1 19 let isValue1 y match y with value1 gt y 1 gt y 我收
  • 如果存在可能的未定义行为,为什么编译器不会警告您?

    我正在读著名的未定义的行为可能导致时间旅行发帖并注意到这部分 首先 您可能会注意到循环中的逐一错误 控制 结果是该函数读取了超过末尾的一位 放弃之前的表数组 经典编译器不会 特别关心 它只会生成代码来读取 越界数组元素 尽管事实上这样做是
  • C#:如何将组合框等项目列表保存到 .NET 设置文件中?

    C 如何将组合框等项目列表保存到 NET 设置文件中 设置设计器允许您使用的唯一集合类型是 System Collections ArrayList 如果您确实使用 ArrayList 则其所有元素的类型都必须是可序列化的 具有 Seria
  • 遗留 C/C++ 项目中的死代码检测 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 您将如何进行 C C 代码中的死代码检测 我有一个相当大的代码库可供使用 并且至少 10 15 是死代码 有没有基于 Unix 的工具来识别这个区域
  • mongodb 和 mongomapper

    我有一个 Rails 应用程序 当前使用 activerecord 来存储和查询产品 每个产品都有一个类别和子类别 每个子类别由我可以在应用程序中创建的多个字段定义 由此 当用户想要输入特定产品时 他们会被按下相关的表单字段 这已经变得非常
  • 贝宝集成问题

    我无法弄清楚我的代码做错了什么 我收到错误 我们检测到该购物车存在问题 如果问题仍然存在 请联系商家 这是我正在提交的表格
  • python内部类的用途是什么?

    Python 的内部 嵌套类让我很困惑 有什么事情是没有他们就无法完成的吗 如果有的话 那是什么东西 引自http www geekinterview com question details 64739 内部类的优点 类的逻辑分组 如果一
  • 用鼠标移动绘制的线

    我试图通过用鼠标抓住一条绘制的线来移动它 这条线已经画好了Graphics DrawLine Pen P Point A Point B 创建线条并将其绘制在表单上绝对没有问题 我试过了 将行添加到GraphicsPath 这甚至没有划清界