更快地创建大量标签

本文关键字:标签 创建 | 更新日期: 2023-09-27 18:36:43

我正在用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();以防止绘图速度变慢,但它仍然非常慢。有没有更好的方法来解决这个问题或我正在做的可能的疏忽?

更快地创建大量标签

若要使用基于TableLayoutPanel的解决方案最大限度地提高效率,请避免在大小更改时重新创建所有Label控件。您可以实现一个方案,以便在大小更改时添加/删除控件;这将执行得更快,但更难设计。

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

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

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

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

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

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 秒即可填充。