问题描述
我正在尝试通过用鼠标抓住一条画线来移动它.
I am trying to move a drawn line by grabbing it with the mouse.
线已经用Graphics.DrawLine(Pen P, Point A, Point B)
画好了.
创建线条并在表格上绘制绝对没有问题.
There is absolutely no problems with creating the Line and drawing it on the form.
我试过了:
将线条添加到
GraphicsPath
- 这甚至不会绘制线条OnPaint
.
Adding the line to a
GraphicsPath
- This does not even draw the lineOnPaint
.
检查 MouseEventArgs e.Location
是否符合一些基本代数(我现在已经丢弃的计算)
Checking if MouseEventArgs e.Location
is on the line with some basic algebra (calculations which I have thrown away as of now)
所以总结一下:我想抓住这条线并将它拖到某个地方,但我什至无法检查 e.Location 是否在线,我该怎么做?
So to sum it up: I want to grab the line and drag it somewhere but I can't even check if e.Location even is on the Line, how do I do this?
这是我使用 GraphicsPath 时代码的外观.
This is how the code looks when I'm using the GraphicsPath.
当我不使用我拥有的 GraphicsPath 时:
When I don't use the GraphicsPath I have:
if (s.thisShape == ShapeType.Line) {
g.DrawLine(pen, s.p1, s.p2);
} else { ... }`
在 drawingShapes 方法中.
in the drawingShapes method.
来自drawStuff:用户控件类:
From the drawStuff : Usercontrol class:
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 类:
From the Shape : Usercontrol class:
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 语句它画得很完美,但我不能把它拖到其他地方.
Now this doesn't even draw the line, however with said if statement in drawingShapes() It draws perfectly but I can not drag it somewhere else.
推荐答案
让我们从基础开始,在屏幕上画一条线.我创建了一个自定义类来处理我希望在此过程中可用的一些功能:
Let's start with the basics, getting a line on the screen. I created a custom class to handle some of the functions I want available to me for this process:
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.
This class provides a few helper functions that will make our life easier. We have properties that return the slope and the Y-intercept, so we can determine if a certain point is on the line. We then provide a helper function IsPointOnLine() that takes a point and a cushion. The cushion is used to simply allow for a user to click close enough to the line to get it to return true.
接下来我将实例化线条并在Form的paint事件中绘制它:
Next I am going to instantiate the line and draw it in the Form's paint event:
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 的线.
Now you should be able to run your application and see a line that goes from 20,20 to 40,40 on the screen.
现在我想处理鼠标与线的交互,所以在 MouseDown 上,我们将查看点击点是否与线相交,是否设置了一个标志并保持我们的增量与端点相交.在 MouseMove 事件中,我们将查看线条是否已被单击但未释放并适当地重置坐标.在 MouseUp 事件中,我们简单地重置我们的标志:
Now I want to handle the mouse interaction with the line, so on MouseDown, we will see if the click point intersects the line and if it is set a flag and keep our deltas from the endpoints. On the MouseMove event, we will see if the line has been clicked but not released and reset the coordinates appropriately. In the MouseUp event, we simple reset our flag:
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 个像素范围内单击并用鼠标移动它.
Now you should be able to click within 5 pixels of the line and have it move with your mouse.
注意,代码中有一些地方需要额外的错误处理,尤其是处理除以 0 错误.
Note, there are some spots in the code that need additional error handling, especially to handle division by 0 errors.
这篇关于用鼠标移动画线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!