带间隙的c#绘画

带间隙的c#绘画,c#,events,paint,C#,Events,Paint,我正在尝试用c语言编写一个小的绘画程序。到目前为止一切正常,唯一的问题是当我移动鼠标足够快时,应该有实线的地方会出现间隙。我已经尝试了从双缓冲到减少鼠标移动事件间隔的所有方法(实际上我没有找到任何方法来做这件事,我认为这对系统上的其他进程也不好^) 你能给我指一下这里的正确方向吗?我尝试覆盖面板的绘制方法,但当我尝试时,似乎什么都没有发生 代码如下: using System; using System.Collections.Generic; using System.ComponentMod

我正在尝试用c语言编写一个小的绘画程序。到目前为止一切正常,唯一的问题是当我移动鼠标足够快时,应该有实线的地方会出现间隙。我已经尝试了从双缓冲到减少鼠标移动事件间隔的所有方法(实际上我没有找到任何方法来做这件事,我认为这对系统上的其他进程也不好^)

你能给我指一下这里的正确方向吗?我尝试覆盖面板的绘制方法,但当我尝试时,似乎什么都没有发生

代码如下:

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;
                    }
            }
        }


    }
}
我明白了:


我不清楚差距在哪里,但你不应该在MouseDown事件中添加第一个点吗?这能解释你看到的差距类型吗

为什么要在MouseDown事件中填充一个矩形


否则,可能是这些间隙的屏幕截图。

鼠标移动事件将跳过-鼠标实际上可以移动得非常快,比事件和应用程序都快。因此,你不会得到一个连续的鼠标移动流,每个像素一个


您需要做的是跟踪上一个鼠标移动中的上一个位置,然后从上一个位置到当前位置绘制一条线,而不是一个点。除非用户将鼠标移动得非常快,否则这将非常接近鼠标的移动速度,以至于您不会注意到它没有精确跟踪每个像素。

我不确定在绘图模式下我们要使用的是哪一个,因此这里有两个版本:

同样值得注意的是,绘制事件处理程序的签名错误,因此可能没有连接到pnlcavas

在绘制代码时,您应该(几乎)不需要调用
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:表单
{
纯色;
列表点列表;
鼠标点;
公共表格1()
{
初始化组件();
pointListe=新列表();
颜色=新的SolidBrush(颜色为黑色);
}
私有void btnClear\u单击(对象发送者,事件参数e)
{
pointListe.Clear();
pnlCanvas.Invalidate();
}
私有void pnlcavas_MouseDown(对象发送方,MouseEventArgs e)
{
添加点列表(例如位置);
}
私有void pnlCanvas_MouseMove(对象发送方,MouseEventArgs e)
{
_鼠标点=e.位置;
pnlCanvas.Invalidate();
}
私有void pnlcavas_Paint(对象发送器,PaintEventArgs e)
{
如果(pointListe.Count>1)
{
e、 绘图线(新钢笔(颜色),pointListe.ToArray());
}
if(pointListe.Any())
{
e、 Graphics.DrawLine(新笔(颜色)、pointListe.Last()、鼠标点);
}
}
}
这将画出一条连续的线:

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:表单
{
纯色;
列表行;
布尔值_mouseDown;
公共表格1()
{
初始化组件();
_行=新列表();
颜色=新的SolidBrush(颜色为黑色);
_mouseDown=false;
}
私有void btnClear\u单击(对象发送者,事件参数e)
{
_行。清除();
pnlCanvas.Invalidate();
}
私有void pnlcavas_MouseDown(对象发送方,MouseEventArgs e)
{
_mouseDown=true;
_添加(新列表());
}
私有void pnlCanvas_MouseMove(对象发送方,MouseEventArgs e)
{
如果(_mouseDown)
{
_lines.Last().Add(例如位置);
pnlCanvas.Invalidate();
}
}
私有无效pnlCanvas_MouseUp(对象发送方,MouseEventArgs e)
{
_mouseDown=false;
}
私有void pnlcavas_Paint(对象发送器,PaintEventArgs e)
{
foreach(变量行集在_行中)
{
如果(lineSet.Count>1)
{
e、 图形.抽绳(新钢笔(颜色),lineSet.ToArray());
}   
}
}
}

给我们一个非英语编写的代码会减少试图帮助你的人的数量。好吧,对不起,我添加了一些注释以供理解。我认为他是在鼠标下画,通过单击画布(只上下,不拖动)来支持画一个“点”。但除此之外,是的,似乎忘记在列表中记录鼠标下降点也会造成一个间隙,初始的“点”后面是一个小的非绘制区域,然后是从第一次鼠标移动开始形成的线。抢手货我在MouseMove方法中添加了点,但是正如我所说的,当我这样做时,没有任何东西被绘制出来。只有当我删除覆盖方法,而不是在MouseMove方法中画线时,它才会给我说的间隙。好的,我添加了一个屏幕截图,并对我之前所做的做了一些解释。我注意到pnlcavas_Paint方法从未被调用,我尝试了一个简单的控制台输出。但它从未被处理过(我不知道我是否在这里遗漏了什么,但这也没有给我任何输出,即使我在pnlcavas_Paint方法的sig中添加了objectsender。注意:我只是手动添加了这个方法,没有其他(可能需要处理程序?)但是我不知道这对于详细的答案是否有任何意义+1。我可以补充一点,如果他想继续而不绘制像素而不是线条,他应该在后位图上绘制,然后在Paint事件处理程序中在画布上绘制该位图。如果不覆盖PaintBackground,您的代码也会产生闪烁(取决于画布),因此我建议先在位图上绘制位图,然后在画布上绘制位图。@user1589728您需要设置pnlcavas.Paint+=new PaintEventHandler(pnlcavas_Paint);在您的代码中。@NikolaD Nick是的,有一点闪烁,我个人会将画布设置为
UserControl
,并将
double buffered
设置为