缓慢添加控件到窗体

时间:2011-08-09 22:01:27

标签: c# controls repaint

为什么油漆甚至需要这么长时间?

public Form1()
    {
        InitializeComponent();
        SuspendLayout();
        double scale = ClientSize.Width / 11;
        for (int i = 1; i < 10; i++)
        {
            for (int j = 1; j < 10; j++)
            {
                everybox[i - 1, j - 1] = new TextBox
                                             {
                                                 Location = new Point((int)(scale * i), (int)(scale * j)),
                                                 Size = new Size((int)scale - 2, (int)scale - 2),
                                                 Multiline = true
                                             };
                Controls.Add(everybox[i - 1, j - 1]);
            }
        }
        ResumeLayout();
    }


private void Form1_Paint(object sender, PaintEventArgs e)
    {
        float scale = ClientSize.Width / 11;
        Graphics g = this.CreateGraphics();
        int counter = 0;
        for (float i = scale; i <= this.ClientSize.Width - scale; i += scale)
        {
            counter++;
            if ((counter - 1) % 3 != 0)
            {
                g.DrawLine(new Pen(Color.Black), new Point((int)i, (int)scale),
                           new Point((int)i, ClientSize.Width - (int)scale));
                g.DrawLine(new Pen(Color.Black), new Point((int)scale, (int)i),
                           new Point(ClientSize.Width - (int)scale, (int)i));
            }
            else
            {
                g.DrawLine(new Pen(Color.Black, 3f), new Point((int)i, (int)scale),
                           new Point((int)i, ClientSize.Width - (int)scale));
                g.DrawLine(new Pen(Color.Black, 3f), new Point((int)scale, (int)i),
                           new Point(ClientSize.Width - (int)scale, (int)i));
            }
        }
    }

这很烦人,导致明显滞后。 everybox是一个TextBox [9,9]对象。

4 个答案:

答案 0 :(得分:1)

根据我的评论,改变:

Graphics g = this.CreateGraphics();

e.Graphics

答案 1 :(得分:0)

可能的原因是因为你试图绘制太多重量级的组件。如果我的数学运算正确,则重绘9 * 9 * 9 * 9 = 6561个对象。 WinForms并非旨在以有效的方式支持重绘那么多组件。

您可能需要考虑是否确实需要使用WinForms中的那么多重量级图形组件。可能有更轻的组件,或者你可以切换到XNA(它有摄像头,视图等 - 所有这些都减少了需要重绘的对象的数量)或WPF,具体取决于上下文。

答案 2 :(得分:0)

绝对可以调用很多,如果你收到过多的调用,它可能与这段代码无关。有助于这一特定位的表现的一件事是尝试减少你的工作量......

    Graphics g = e.Graphics;
    Pen bp = new Pen(Color.Black, 3f);
    Point start = new Point(0,0);
    Point stop = new Point(0,0);

    for (float i = scale; i <= this.ClientSize.Width - scale; i += scale)
    {
        int iAsInt = (int)i;
        int scaleAsInt = (int)scale;
        int w = ClientSize.Width;
        counter++;

        if ((counter - 1) % 3 != 0)
        {
            start.X = iAsInt;
            start.Y = scaleAsInt;
            stop.X = iAsInt;
            stop.Y = w-scaleAsInt;
            g.DrawLine(Pens.Black, start, stop);
            start.X = scaleAsInt;
            start.Y = iAsInt;
            stop.X = w-scaleAsInt;
            stop.Y = iAsInt;
            g.DrawLine(Pens.Black, start, stop);
            // Note: this looks like more work, but it is actually less
            // your code still has to make all the assignments in addition to 
            // newing up the points (and later having to garbage collect them)
        }
        else
        {
            // TODO: reuse the start/stop points here
            g.DrawLine(bp, new Point(iAsInt, scaleAsInt), new Point(iAsInt, w - scaleAsInt);
            g.DrawLine(bp, new Point(scaleAsInt, iAsInt), new Point(w - scaleAsInt, iAsInt));
        }
    }

要专门停止过度绘制线条,请查看PaintEventArgs的ClipRectangle成员。如果你的部分线落在剪辑矩形的区域内,则重绘它。

答案 3 :(得分:0)

您发布的代码会导致paint事件触发81次(9 * 9)。一次为每个控件添加到表单中。任何时候都是由于某些东西使表单无效,比如鼠标在它上面移动,另一个窗口移动它,或者表单调整大小。您未向我们展示的某些代码可能会负责。