我想通过鼠标绘制一条线(交互式),我使用C#和WinForm,该线应该在任何时候从起点(当鼠标按在面板上时)到鼠标的当前位置时出现比如在画图程序中画一条线。
但代码产生了很多行,我知道为什么,但我不知道如何克服这个问题
这是我的代码:
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Graphics g;
Pen myPen = new Pen(Color.Red);
Point p = new Point();
bool flag = false;
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
flag = true;
p = e.Location;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (flag)
{
g = panel1.CreateGraphics();
myPen.Width = 3;
Point p2 = new Point();
p2 = e.Location;
g.DrawLine(myPen, p, p2);
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
flag = false;
}
}}
任何帮助?我想绘制很多行并尽可能简化代码!
答案 0 :(得分:1)
您需要更好地管理绘图。一些指示:
CreateGraphics
。相反,请使用控件已提供的Paint
事件。Form
类中绘图。这是一个示例类。它继承自Panel
。只需将其添加到表单中,例如在Form的构造函数中使用this.Controls.Add(new PanelWithMouseDraw());
。
注意:这使用Tuple
我认为需要.NET 4.0或更高版本。你可以用其他东西替换这个结构,如果需要的话......你只需要保留一个Point
对列表。
namespace WindowsFormsApplication1
{
public class PanelWithMouseDraw : Panel
{
private Point _origin = Point.Empty;
private Point _terminus = Point.Empty;
private Boolean _draw = false;
private List<Tuple<Point, Point>> _lines = new List<Tuple<Point, Point>>();
public PanelWithMouseDraw()
{
Dock = DockStyle.Fill;
DoubleBuffered = true;
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left)
{
_draw = true;
_origin = e.Location;
}
else
{
_draw = false;
_origin = Point.Empty;
}
_terminus = Point.Empty;
Invalidate();
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (_draw && !_origin.IsEmpty && !_terminus.IsEmpty)
_lines.Add(new Tuple<Point, Point>(_origin, _terminus));
_draw = false;
_origin = Point.Empty;
_terminus = Point.Empty;
Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left)
_terminus = e.Location;
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
foreach (var line in _lines)
e.Graphics.DrawLine(Pens.Blue, line.Item1, line.Item2);
if (!_origin.IsEmpty && !_terminus.IsEmpty)
e.Graphics.DrawLine(Pens.Red, _origin, _terminus);
}
}
}
答案 1 :(得分:0)
简单修复,按如下方式更改方法panel1_MouseMove
:
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (flag)
{
g = panel1.CreateGraphics();
myPen.Width = 3;
Point p2 = new Point();
p2 = e.Location;
g.DrawLine(myPen, p, p2);
p = p2; // just add this
}
}
请记住,这对任何鼠标按钮都有效,左或右无关紧要。
EDIT1:
这应画一条直线和之前的所有。
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public struct Line
{
public Point start;
public Point end;
}
public Form1()
{
InitializeComponent();
}
Pen erasePen = new Pen(Color.White, 3.0F);
Pen myPen = new Pen(Color.Red, 3.0F);
Point p = new Point();
Point endPoint = new Point();
bool flag = false;
List<WindowsFormsApplication2.Form1.Line> lines = new List<WindowsFormsApplication2.Form1.Line>();
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
flag = true;
p = e.Location;
endPoint = p;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (flag)
{
Graphics g = panel1.CreateGraphics();
Point p2 = e.Location;
EraseLine(p, endPoint, g);
DrawAllLines(lines, g);
DrawLine(p, p2, g);
endPoint = p2;
g.Dispose();
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
// redraw for one last time...
Graphics g = panel1.CreateGraphics();
Point p2 = e.Location;
lines.Add(new Line { start = p, end = p2} );
EraseLine(p, endPoint, g);
DrawAllLines(lines, g);
flag = false;
g.Dispose();
}
private void DrawLine(Point start, Point end, Graphics g)
{
g.DrawLine(myPen, start, end);
}
private void DrawLine(WindowsFormsApplication2.Form1.Line line, Graphics g)
{
g.DrawLine(myPen, line.start, line.end);
}
private void DrawAllLines(List<WindowsFormsApplication2.Form1.Line> allLines, Graphics g)
{
foreach(WindowsFormsApplication2.Form1.Line l in allLines)
{
g.DrawLine(myPen, l.start, l.end);
}
}
private void EraseLine(Point start, Point end, Graphics g)
{
g.DrawLine(erasePen, start, end);
}
}}