我在C#中有一个带有绘图面板和按钮的Windows窗体应用程序 - 用于绘制线条。
单击该按钮时,可以绘制2个随机点的直线。
Pen p = new Pen(Color.Black, 5);
//point for start
Point ps = new Point();
//point for end
Point pe = new Point();
private void drawPanel_MouseDown(object sender, MouseEventArgs e)
{
ps.X = e.X;
ps.Y = e.Y;
pe = ps;
}
private void drawPanel_MouseMove(object sender, MouseEventArgs e)
{
// when button is clicked for drawing draw = true;
if (draw)
{
if (e.Button == MouseButtons.Left)
{
pe = new Point(e.X, e.Y);
}
}
}
private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
onMouseUpFlag = true;
}
private void drawPanel_Paint(object sender, PaintEventArgs e)
{
Graphics g = drawPanel.CreateGraphics();
if (onMouseUpFlag)
{
g.DrawLine(p, ps, pe);
g.Dispose();
}
}
该计划存在一些缺陷:
有关如何修复这些错误的任何建议吗?
修改
我已经读了你的答案并做了一些改变:
Pen p = new Pen(Color.Black, 5);
Point ps = new Point();
Point pe = new Point();
List<Point> linesStart= new List<Point>();
List<Point> linesEnd= new List<Point>();
private void drawPanel_MouseDown(object sender, MouseEventArgs e)
{
ps.X = e.X;
ps.Y = e.Y;
linesStart.Add(ps);
pe = ps;
}
private void drawPanel_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
pe = new Point(e.X, e.Y);
//adding end point .. actually adds a lot of points
linesEnd.Add(pe);
}
}
bool onMouseUpFlag = false;
private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
onMouseUpFlag = true;
drawPanel.Invalidate();
}
private void drawPanel_Paint(object sender, PaintEventArgs e)
{
if (onMouseUpFlag)
{
for (int i = 0; i < linesStart.Count; i++)
{
e.Graphics.DrawLine(p, linesStart[i], linesEnd[i]);
}
}
}
现在我正在尝试为多行修复DrawLine。 Paint事件可以做多行,但只有起点可以。不知怎的,终点不是很正确。我可以在哪里准确设置MouseMove事件的最后一点?
答案 0 :(得分:3)
您必须在面板上调用Invalidate方法:
private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
onMouseUpFlag = true;
drawPanel.Invalidate();
}
另外,使用PaintEvent中的Graphic对象:
private void drawPanel_Paint(object sender, PaintEventArgs e)
{
if (onMouseUpFlag)
{
e.Graphics.DrawLine(p, ps, pe);
}
}
对于多行,您必须将点保存在集合对象中。
根据您更新的代码,以下是我认为您尝试执行的操作示例:
private class Line {
public Point Starting { get; set; }
public Point Ending { get; set; }
public Line(Point starting, Point ending) {
this.Starting = starting;
this.Ending = ending;
}
}
List<Line> lines = new List<Line>();
private Point downPoint = Point.Empty;
private Point movePoint = Point.Empty;
private bool movingLine = false;
public Form1() {
InitializeComponent();
panel1.Paint += panel1_Paint;
panel1.MouseDown += panel1_MouseDown;
panel1.MouseMove += panel1_MouseMove;
panel1.MouseUp += panel1_MouseUp;
}
void panel1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
downPoint = e.Location;
}
}
void panel1_MouseMove(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
movingLine = true;
movePoint = e.Location;
panel1.Invalidate();
}
}
void panel1_MouseUp(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
movingLine = false;
lines.Add(new Line(downPoint, e.Location));
panel1.Invalidate();
}
}
void panel1_Paint(object sender, PaintEventArgs e) {
e.Graphics.Clear(Color.White);
foreach (Line l in lines) {
e.Graphics.DrawLine(Pens.Black, l.Starting, l.Ending);
}
if (movingLine) {
e.Graphics.DrawLine(Pens.Black, downPoint, movePoint);
}
}
使用inherited panel打开DoubleBuffer属性以避免闪烁。
答案 1 :(得分:1)
每当您想要重绘(在您的代码中)时,您应该调用panelinvalidate drawPanel.Invalidate()
。
完成鼠标移动并释放按钮
private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
onMouseUpFlag = true;
drawPanel.Invalidate();
}
最后我建议在你的drawPanel_Paint中使用这个代码而不是你的代码 。您应该使用EventArgs提供的Graphics,而不是创建新的。
private void drawPanel_Paint(object sender, PaintEventArgs e)
{
if (onMouseUpFlag)
{
e.Graphics.DrawLine(p, ps, pe);
}
}
答案 2 :(得分:1)
您需要在放开鼠标后触发重绘事件。只需调用drawPanel.Invalidate()
即可重新绘制表单。
要绘制多行,您必须将每个行的信息存储在列表或其他内容中,并在重绘中绘制每一行。 Paint方法基本上每次都以空格开头,因此它只会以您当前设置的方式绘制最新的方式。