1

我正在用winforms编写一个Picross求解程序,其中网格可以调整大小以允许求解不同的大小。我一直在使用 aList<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();在调用它之前的函数中以防止绘制速度变慢,但它仍然非常慢。有没有更好的方法来解决这个问题或我正在做的可能的疏忽?

4

3 回答 3

2

为了最大限度地提高基于 a 的解决方案的效率TableLayoutPanel,请避免在大小更改时重新创建所有Label控件。您可以实施一个方案来随着大小的变化添加/删除控件;这将执行得更快,但更难设计。

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

  • 避免重复算术:i * newSize + j只计算一次并将结果分配给局部变量。
  • 使用TableLayoutPanel.Controls.AddRange方法而不是TableLayoutPanel.Controls.Add. 这可能会阻止暂时“冻结”的 UI。
  • 尝试设置TableLayoutPanel.DoubleBuffered = true。这样做的目的是防止在重要的 UI 区域发生变化时出现闪烁,但它也可以加快速度。
于 2013-10-24T04:49:41.770 回答
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 秒。

于 2013-10-24T04:00:53.223 回答
0

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

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

于 2013-10-24T03:39:39.813 回答