C# 向窗体缓慢添加控件

C# 向窗体缓慢添加控件,c#,controls,repaint,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++) {

为什么油漆要花这么长时间

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));
            }
        }
    }
public Form1()
{
初始化组件();
SuspendLayout();
双刻度=ClientSize.Width/11;
对于(int i=1;i<10;i++)
{
对于(int j=1;j<10;j++)
{
everybox[i-1,j-1]=新文本框
{
位置=新点((int)(标度*i),(int)(标度*j)),
尺寸=新尺寸((整数)比例-2,(整数)比例-2),
多行=真
};
Add(everybox[i-1,j-1]);
}
}
恢复布局();
}
私有void Form1_Paint(对象发送器、PaintEventArgs e)
{
浮动比例=ClientSize.Width/11;
Graphics g=this.CreateGraphics();
int计数器=0;

对于(float i=scale;i,一个可能的原因是您试图绘制太多的权重组件。如果我的数学正确,您正在重新绘制9*9*9*9=6561个对象。WinForms的设计不支持以高效的方式重新绘制那么多组件


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

Paint肯定会被多次调用,如果调用过多,则可能与这段代码无关。有一件事可以帮助提高这段代码的性能,那就是尽量减少所做的工作量

    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));
        }
    }
Graphics g=e.Graphics;
笔bp=新笔(颜色为黑色,3f);
点开始=新点(0,0);
点停止=新点(0,0);

对于(float i=scale;i您发布的代码导致绘制事件触发81次(9*9)。对于添加到表单中的每个控件一次。任何更多的时间都是由于某种原因导致表单无效,例如鼠标在其上移动、另一个窗口在其上移动或表单大小调整。您没有向我们显示的某些代码可能对此负责。

根据我的评论,更改:

Graphics g = this.CreateGraphics();


XNA当然是用于开发游戏的。WPF会是一个更好的等价物,例如,它支持交互控制。我没有遵循。我画了81个文本框和121行。当我单独做每一个时,它们都不会占用可接受的时间。当我一起做时,大约需要半秒钟。而这是一个游戏,它是数独,而不是我想要的通常称为图形密集型。我只是想知道为什么绘制事件会引发两次以上。@soandos AFAIK绘制事件会在循环中不断被调用,以重新绘制窗口中的所有图形。也许可以尝试快速分析会话,看看是什么消耗了您的CPU?@oleskii:绘制事件仅在控件重新绘制时触发,而ch只有在有理由重新绘制时才会发生。不是在循环中。请原谅,但这如何防止线被多次绘制?它如何减少绘制线调用的次数?我最初的回答没有,但我试图帮助解决您的滞后问题。我在最后添加了一点,特别是关于您的透支问题lem。但是命令的数量是一样的。只是数学更简单。不,事实并非如此。此外,所有控件都是在没有调用单个绘制事件的情况下添加的。没有其他代码(空加载事件)@soandos:是这样的。添加控件时不会调用paint事件,因为在创建窗口之前,您正在构造函数中执行此操作。当您显示表单时,将调用paint事件。此时,它将被调用81次。此后,每当表单失效时,它都会再次被调用。将其更改为e.graphics让它变得即时。谢谢。我将我的评论更改为下面的答案。谢谢。它调用了很多次。现在绘制功能甚至没有在探查器上显示为强化功能,谢谢。如果你发布它,我将接受这一回答。我很抱歉。在我看来,我的绘制活动占用了大量的my处理器时间。它似乎被调用了很多次。我将编辑我的问题。
e.Graphics