我正在尝试用c#做一个小的绘画程序。到目前为止一切正常,唯一的事情就是当我快速移动鼠标时,间隙出现在应该有实线的地方。我已尝试从双缓冲到减少mouse_move事件的间隔(我实际上没有找到任何方法来执行此操作,我认为这对系统上的其他进程也是坏的^^)
你能指出我在正确的方向吗?我尝试重写面板的绘制方法,但是当我尝试这种情况似乎没有发生。这是代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Paint
{
public partial class Form1 : Form
{
bool paint;
SolidBrush color;
//size of brush
int pinselGröße;
List<Point> pointListe;
public Form1 ()
{
InitializeComponent ();
pointListe = new List<Point>();
paint = false;
color = new SolidBrush ( Color.Black );
//get brush size from combobox
pinselGröße = Convert.ToInt32 ( nudBrushSize.Value );
}
private void btnExit_Click ( object sender, EventArgs e )
{
this.Close ();
}
private void btnClear_Click ( object sender, EventArgs e )
{
Graphics gfx = pnlCanvas.CreateGraphics ();
gfx.Clear ( pnlCanvas.BackColor );
}
private void pnlCanvas_MouseDown ( object sender, MouseEventArgs e )
{
paint = true;
Graphics grfx = pnlCanvas.CreateGraphics ();
//draw a rectangle with brush "color" and pinselGröße as the brush size
grfx.FillRectangle ( color, e.X, e.Y, pinselGröße, pinselGröße );
}
private void pnlCanvas_MouseMove ( object sender, MouseEventArgs e )
{
if ( paint )
{
//Graphics grfx = pnlCanvas.CreateGraphics();
////put old position of mouse into variable
//int altePosX = e.X;
//int altePosY = e.Y;
////grfx.FillEllipse ( color, e.X, e.Y, pinselGröße, pinselGröße );
//grfx.FillRectangle(color, e.X, e.Y, pinselGröße, pinselGröße);
//grfx.Dispose();
pointListe.Add(e.Location);
pnlCanvas.Invalidate();
}
}
private void pnlCanvas_Paint(PaintEventArgs e)
{
e.Graphics.DrawLines(new Pen(color), pointListe.ToArray());
}
private void pnlCanvas_MouseUp ( object sender, MouseEventArgs e )
{
paint = false;
}
private void nudBrushSize_ValueChanged ( object sender, EventArgs e )
//when value of combobox changes, read value into brush size variable
pinselGröße = Convert.ToInt32 ( nudBrushSize.Value );
}
private void cmbColor_SelectedIndexChanged ( object sender, EventArgs e )
{
int index = cmbColor.SelectedIndex;
color.Dispose ();
switch ( index )
{
case 0:
{
color = new SolidBrush ( Color.Black );
break;
}
case 1:
{
Console.WriteLine ( "Geht" );
color = new SolidBrush ( Color.Red );
break;
}
case 2:
{
color = new SolidBrush ( Color.Blue );
break;
}
case 3:
{
color = new SolidBrush ( Color.Green );
break;
}
}
}
}
}
当我这样做时:
private void pnlCanvas_MouseMove ( object sender, MouseEventArgs e )
{
if ( paint )
{
Graphics grfx = pnlCanvas.CreateGraphics();
////put old position of mouse into variable
int altePosX = e.X;
int altePosY = e.Y;
//grfx.FillEllipse ( color, e.X, e.Y, pinselGröße, pinselGröße );
grfx.FillRectangle(color, e.X, e.Y, pinselGröße, pinselGröße);
grfx.Dispose();
//pointListe.Add(e.Location);
//pnlCanvas.Invalidate();
}
}
//private void pnlCanvas_Paint(PaintEventArgs e)
//{
// Console.Write("mjsda2");
// e.Graphics.DrawLines(new Pen(color), pointListe.ToArray());
//}
我明白了:
答案 0 :(得分:4)
我不确定我们在绘图模式中的用途,所以这里有两个版本:
另外值得注意的是,你的paint事件处理程序有错误的签名,因此可能没有连接到pnlCanvas。
在做油漆代码时,您(几乎)永远不需要致电CreateGraphics
- 它通常表示“你做错了”。
这会让您点击点来绘制线条:
public partial class Form1 : Form
{
SolidBrush color;
List<Point> pointListe;
Point _mousePoint;
public Form1()
{
InitializeComponent();
pointListe = new List<Point>();
color = new SolidBrush(Color.Black);
}
private void btnClear_Click(object sender, EventArgs e)
{
pointListe.Clear();
pnlCanvas.Invalidate();
}
private void pnlCanvas_MouseDown(object sender, MouseEventArgs e)
{
pointListe.Add(e.Location);
}
private void pnlCanvas_MouseMove(object sender, MouseEventArgs e)
{
_mousePoint = e.Location;
pnlCanvas.Invalidate();
}
private void pnlCanvas_Paint(object sender, PaintEventArgs e)
{
if (pointListe.Count > 1)
{
e.Graphics.DrawLines(new Pen(color), pointListe.ToArray());
}
if (pointListe.Any())
{
e.Graphics.DrawLine(new Pen(color), pointListe.Last(), _mousePoint);
}
}
}
这将绘制一条连续线:
public partial class Form1 : Form
{
SolidBrush color;
List<List<Point>> _lines;
Boolean _mouseDown;
public Form1()
{
InitializeComponent();
_lines = new List<List<Point>>();
color = new SolidBrush(Color.Black);
_mouseDown = false;
}
private void btnClear_Click(object sender, EventArgs e)
{
_lines.Clear();
pnlCanvas.Invalidate();
}
private void pnlCanvas_MouseDown(object sender, MouseEventArgs e)
{
_mouseDown = true;
_lines.Add(new List<Point>());
}
private void pnlCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (_mouseDown)
{
_lines.Last().Add(e.Location);
pnlCanvas.Invalidate();
}
}
private void pnlCanvas_MouseUp(object sender, MouseEventArgs e)
{
_mouseDown = false;
}
private void pnlCanvas_Paint(object sender, PaintEventArgs e)
{
foreach (var lineSet in _lines)
{
if (lineSet.Count > 1)
{
e.Graphics.DrawLines(new Pen(color), lineSet .ToArray());
}
}
}
}
答案 1 :(得分:2)
我不清楚差距在哪里发生,但是你不应该在MouseDown事件中添加你的第一个点吗?这可以解释你所看到的差距类型吗?
为什么要在MouseDown事件中填充矩形?
否则,也许是这些差距的截图。
答案 2 :(得分:2)
Mousemove事件将跳过 - 鼠标实际上可以移动得非常快,比事件更快,你的应用程序可以跟上。结果,你不会得到一个很好的连续的鼠标移动流,每个像素一个。
您需要做的是跟踪您在上一次鼠标移动中获得的上一个位置,然后绘制一个点,而不是从前一个位置到当前位置的一条线。除非用户疯狂地移动鼠标,否则这将近似于鼠标移动得足够好,以至于您不会注意到它没有完全跟踪每个像素。