更快地创建大量标签?

时间:2013-10-24 02:37:40

标签: c# winforms

我正在winforms中编写一个Picross求解程序,其中网格可以调整大小以允许解决不同的大小。我一直在使用List<System.Windows.Forms.Label>为网格的每个方格保留一个标签,但是当我将网格大小调整为15x15以上的大小时,为了简单地调整网格大小,它往往需要几秒钟。虽然我不认为网格大小的快速切换是常见的,但我希望网格不需要花费10秒钟来填充标签。

System.Windows.Forms.TableLayoutPanel PicrossGrid;
List<System.Windows.Forms.Label> PicrossGridLabel;

private void adjustGridLabel(int newSize)
{
    System.Windows.Forms.Label[] temp = new System.Windows.Forms.Label[newSize*newSize]; 
    for (int i = 0; i < newSize; i++)
    {
        for (int j = 0; j < newSize; j++)
        {
            temp[i * newSize + j] = new System.Windows.Forms.Label();
            temp[i * newSize + j].Anchor = System.Windows.Forms.AnchorStyles.None;
            temp[i * newSize + j].AutoSize = true;
            temp[i * newSize + j].Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            temp[i * newSize + j].Location = new System.Drawing.Point(i, j);
            temp[i * newSize + j].Name = "PicrossGridLabelC" + (i + 1) + "R" + (j + 1);
            temp[i * newSize + j].Size = new System.Drawing.Size(24, 30);
            temp[i * newSize + j].TabIndex = (i * 5) + j;
            temp[i * newSize + j].Text = "X";
            temp[i * newSize + j].TextAlign = System.Drawing.ContentAlignment.TopCenter;
            PicrossGrid.Controls.Add(temp[i * newSize + j], i, j);
        }
    }
    PicrossGridLabel = temp.ToList();
 }

我还在函数中放置this.SuspendLayout();之前调用它以防止绘图减速,但它仍然非常慢。有没有更好的方法来解决这个问题,或者我正在制定可能的疏忽?

3 个答案:

答案 0 :(得分:2)

要使用基于TableLayoutPanel的解决方案最大限度地提高效率,请避免在大小更改时重新创建所有Label控件。你可以实现一个方案来随着大小的变化添加/删除控件;这会更快,但设计起来更困难。

提高重新创建方法效率的一些建议:

  • 避免重复算术:仅计算一次i * newSize + j并将结果分配给局部变量。
  • 使用TableLayoutPanel.Controls.AddRange方法代替TableLayoutPanel.Controls.Add。这可能会阻止暂时“冻结”的用户界面。
  • 尝试设置TableLayoutPanel.DoubleBuffered = true。这样做的目的是在重要UI区域发生变化时防止闪烁,但也可以加快速度。

答案 1 :(得分:0)

如果我理解你的问题,这就是GDI的问题。自Windows Vista以来,视频卡驱动程序模型仅提供GDI操作的一小部分硬件加速。因此,当您开始以编程方式调整窗口大小时,大多数GDI操作都会执行。

据我所知,唯一的解决方案是WPF。

答案 2 :(得分:0)

您还可以通过删除数组然后将控件集合转换为列表来节省大量时间。

System.Windows.Forms.TableLayoutPanel PicrossGrid;
List<PiCrossLabel> PicrossGridLabel;

private void adjustGridLabel(int newSize)
{
    for (int i = 0; i < newSize; i++)
    {
        for (int j = 0; j < newSize; j++)
        {
                PiCrossLabel NewLabel = new PiCrossLabel();
                NewLabel.Name = "PicrossGridLabelC" + (i + 1) + "R" + (j + 1);
                TabIndex = (i * 5) + j;
                PicrossGrid.Controls.Add(NewLabel, i, j);
        }
    }
    PicrossGridLabel = temp.ToList();
 }

public class PiCrossLabel:Label
{
    public PiCrossLabel()
    {
        this.Anchor = System.Windows.Forms.AnchorStyles.None;
        this.AutoSize = true;
        this.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        this.Size = new System.Drawing.Size(24, 30);
        this.Text = "X";
        this.TextAlign = System.Drawing.ContentAlignment.TopCenter;            
    }
}

在我的系统上,20X20可以填充大约4秒钟。