C# 图表点和绘图线

C# 图表点和绘图线,c#,winforms,gdi+,C#,Winforms,Gdi+,我想创建一个有3个点的图表,然后画一条线。如下图所示 ![表格][1] 但我的代码几乎没有画线,也没有点。请帮忙 public partial class Form5 : Form { public Form5() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Point[] pts = { new P

我想创建一个有3个点的图表,然后画一条线。如下图所示 ![表格][1] 但我的代码几乎没有画线,也没有点。请帮忙

public partial class Form5 : Form
{
    public Form5()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Point[] pts = { new Point(150, 12), new Point(130, 15), new Point(160, 18) };
        //int count = 0;

      //   pts[count] = new Point((int)NumericUpDown1.Value, (int)NumericUpDown2.Value);
        for (int i = 0; i < pts.Length; i++)
        {
            if (i != 0)
            {
                this.CreateGraphics().DrawLine(new Pen(Brushes.Black, 3), pts[i - 1], pts[1]);
            }
            else
            {
                this.CreateGraphics().DrawLine(new Pen(Brushes.Black, 3), pts[i], pts[1]);
            }
        }
    }
}
公共部分类表单5:表单
{
公共表格5()
{
初始化组件();
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
点[]分={新点(150,12)、新点(130,15)、新点(160,18)};
//整数计数=0;
//pts[count]=新点((int)NumericUpDown1.Value,(int)NumericUpDown2.Value);
对于(int i=0;i
代码中的主要问题是硬编码
pts[1]
。您应该改用
pts[i]
。记住——C#中的数组索引从零开始

此外,您不需要在每次迭代中创建图形。声明局部变量并将其移到循环外部。不必在每次迭代中检查循环值,您也可以将第一个点图形移到循环外。然后,您将能够以相同的方式处理其他点:

var g = this.CreateGraphics();
var blackPen = new Pen(Brushes.Black, 3);

g.DrawLine(blackPen, pts[0], pts[0]);

for(i = 1; i < pts.Length; i++)
   g.DrawLine(blackPen, pts[i - 1], pts[i]);

代码中的主要问题是硬编码
pts[1]
。您应该改用
pts[i]
。记住——C#中的数组索引从零开始

此外,您不需要在每次迭代中创建图形。声明局部变量并将其移到循环外部。不必在每次迭代中检查循环值,您也可以将第一个点图形移到循环外。然后,您将能够以相同的方式处理其他点:

var g = this.CreateGraphics();
var blackPen = new Pen(Brushes.Black, 3);

g.DrawLine(blackPen, pts[0], pts[0]);

for(i = 1; i < pts.Length; i++)
   g.DrawLine(blackPen, pts[i - 1], pts[i]);

以下是正确的代码:

// keep your data at class level:
// lists are more flexible than arrays:
List<Point> pts = new List<Point>();

 // all drawing in the paint event:
private void Form1_Paint(object sender, PaintEventArgs e)
{

    // put the pen creation in a using scope:
    using ( Pen Pen = new Pen(Color.Red, 3f) )
    {  
        // make the corners nicer:
        pen.MiterLimit = pen.Width / 2f;

        // drawing all lines in one call greatly improves quality.
        // we need at least two points:
        if (pts.Count > 1) e.Graphics.DrawLines( Pen, pts);
    }
}

// trigger the drawing when needed, eg when you have added more points:
private void button1_Click(object sender, EventArgs e)
{
    // maybe add more points..
    pts.AddRange( new Point[]  
                { new Point(150, 12), new Point(130, 15), new Point(160, 18) } );

    // trigger the paint event
    this.Invalidate();
}
请注意,我已对点进行了排序,但并非所有图表类型都需要这样做。我用的是Fastline,你的原始订单也可以。它甚至可以显示多个具有相同X值的点。。!当然,它会自动伸缩

还请注意,图表以自然的方式显示Y值,即从下到上,而GDI是从上到下绘制的

以下是显示图表的两种方法的屏幕截图:


以下是正确的代码:

// keep your data at class level:
// lists are more flexible than arrays:
List<Point> pts = new List<Point>();

 // all drawing in the paint event:
private void Form1_Paint(object sender, PaintEventArgs e)
{

    // put the pen creation in a using scope:
    using ( Pen Pen = new Pen(Color.Red, 3f) )
    {  
        // make the corners nicer:
        pen.MiterLimit = pen.Width / 2f;

        // drawing all lines in one call greatly improves quality.
        // we need at least two points:
        if (pts.Count > 1) e.Graphics.DrawLines( Pen, pts);
    }
}

// trigger the drawing when needed, eg when you have added more points:
private void button1_Click(object sender, EventArgs e)
{
    // maybe add more points..
    pts.AddRange( new Point[]  
                { new Point(150, 12), new Point(130, 15), new Point(160, 18) } );

    // trigger the paint event
    this.Invalidate();
}
请注意,我已对点进行了排序,但并非所有图表类型都需要这样做。我用的是Fastline,你的原始订单也可以。它甚至可以显示多个具有相同X值的点。。!当然,它会自动伸缩

还请注意,图表以自然的方式显示Y值,即从下到上,而GDI是从上到下绘制的

以下是显示图表的两种方法的屏幕截图:


-3:Winforms的每一个绘图错误都是:您应该使用绘图线和绘制事件!你应该扔掉这支笔@你在我的回答中看到事件处理程序了吗?答案是无效的?通常我使用Pen/Brush和其他gdi对象作为类字段,并在表单dispose中处理它们-1用于将有效答案标记为“无用”,这是一个谎言。如果您有需要改进的地方,您不能更新投票或写评论。您继续使用CreateGraphics,这清楚地表明您没有使用paint事件。因此,你的答案不仅没有用处,而且有害。至于你对我的回答投了反对票,认为这无助于报复,这显然违反了所有投票规则。你说我是骗子,让我(几乎)说不出话来。@TaW 1)我正在解决OP面临的问题。没有命名,没有其他东西。如果OP有
CreateGraphics
方法,那么他可能有理由使用该方法。我不会在绘制线逻辑之外修改代码。我正在回答这个问题并给出一些建议。2) 我没有看到任何违反SO规则的情况。我发现你的答案对OP问题没有帮助。您只需重写所有代码并按原样提供。我在对您的答案的评论中指出了这一点-3:每一个Winforms绘图错误都是:您应该使用绘图线和绘制事件!你应该扔掉这支笔@你在我的回答中看到事件处理程序了吗?答案是无效的?通常我使用Pen/Brush和其他gdi对象作为类字段,并在表单dispose中处理它们-1用于将有效答案标记为“无用”,这是一个谎言。如果您有需要改进的地方,您不能更新投票或写评论。您继续使用CreateGraphics,这清楚地表明您没有使用paint事件。因此,你的答案不仅没有用处,而且有害。至于你对我的回答投了反对票,认为这无助于报复,这显然违反了所有投票规则。你说我是骗子,让我(几乎)说不出话来。@TaW 1)我正在解决OP面临的问题。没有命名,没有其他东西。如果OP有
CreateGraphics
方法,那么他可能有理由使用该方法。我不会在绘制线逻辑之外修改代码。我正在回答这个问题并给出一些建议。2) 我没有看到任何违反SO规则的情况。我发现你的答案对OP问题没有帮助。您只需重写所有代码并按原样提供。我在对你的答案的评论中提到了这一点——很多问题。这个答案与OP问题无关。OP问题没有给出答案。命名很糟糕-
pts
而不是
points
、button1、button2等。此外,每次单击按钮都会将另一组相同的点添加到
pts
列表中。这是一个错误。你应该阅读我的代码,包括注释,而不是写注释。当然,如果命名有助于OP与他的项目代码相关联,那么就应该继续命名。。这里没有需要修复的bug。与其争论,不如阅读我的评论和问题。另外,如果你能仔细阅读我的文章,那也会很好。但是你有吗?也许你忘记了一些事情。。不,我不会再和你争论了。不幸的是你没有。不足为奇。但很高兴听到你停止争论了。也许下一次你会发现很多问题。这个答案没有关系