动态创建的PictureBox渲染问题

Dynamically created PictureBox rendering problem

最终目标是一个有点可玩的记忆游戏。目前,我陷入了渲染问题。我有以下 类:

字段,这是一个抽象UserControl:

public abstract class Field : UserControl
{
    protected PictureBox _pictureBox;

    public Field()
    {
        _pictureBox = new PictureBox();
        _pictureBox.Image = Properties.Resources.empty;
        _pictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
        _pictureBox.BorderStyle = BorderStyle.FixedSingle;
        this.Controls.Add(_pictureBox);
    }

    // ...
    // some abstract methods, not currently important
}

MemoryField,派生自 Field:

public class MemoryField : Field
{
    public MemoryField(Form parent, int xPos, int yPos, int xSize, int ySize)
    {
        _pictureBox.ClientSize = new Size(xSize, ySize);
        _pictureBox.Location = new Point(xPos, yPos);
        _pictureBox.Parent = parent;
    }

    // ...
}

最后,MainForm 这是我的应用程序的入口点:

public partial class MainForm : Form
{
    private readonly int fieldWidth = 100; // 150 no rendering problems at all
    private readonly int fieldHeight = 100;

    public MainForm() { InitializeComponent(); }

    private void MainForm_Load(object sender, EventArgs e)
    {
        for (int y = 0; y < 6; y++) // 6 rows
        {
            for (int x = 0; x < 10; x++) // 10 columns
            {
                Field field = new MemoryField(this, 
                    x * (fieldWidth + 3), // xPos, 3 is for a small space between fields
                    labelTimer.Location.Y + labelTimer.Height + y * (fieldHeight + 3), // yPos
                    fieldWidth, 
                    fieldHeight);

                this.Controls.Add(field);
            }
        }
    }
}

这是我的问题所在: 在那些 for 循环中,我试图生成一个 6x10 的 Field 网格(每个网格包含一个 PictureBox 100x100 像素的大小)。我这样做几乎成功了,因为我的第二个字段没有正确呈现:

我发现唯一可行的(完全解决了问题)是使字段更大(即 150 像素)。另一方面,将其变小(即 50px)会使问题变得更大:


也许有用的信息和我试过的东西:

当然,我可以将大小更改为 150px 然后继续,但我真的很想知道这个问题的根源是什么。谢谢!

解决问题最简单的方法是您已经尝试过的方法 - 直接使用 PictureBox 而不是 Field。现在,考虑到您只使用 Field 来包装 PictureBox,您可以继承 PictureBox 而不是仅仅包装它。 将您的 类 更改为这些将解决您注意到的问题:

public abstract class Field : PictureBox {

    public Field() {
        Image = Image.FromFile(@"Bomb01.jpg");
        SizeMode = PictureBoxSizeMode.StretchImage;
        BorderStyle = BorderStyle.FixedSingle;
        Size = new Size(100, 100);
    }

    // ...
    // some abstract methods, not currently important
}

public class MemoryField : Field {
    public MemoryField(Form parent, int xPos, int yPos, int xSize, int ySize) {
        ClientSize = new Size(xSize, ySize);
        Location = new Point(xPos, yPos);
    }

    // ...
}

它不起作用的真正原因与每个 Field 及其子组件的 sizingpositioning 有关.您不应相对于其父级 MemoryField 设置每个 _pictureBoxLocation,而是相对于其父级 [=24] 更改 MemoryFieldLocation =].

您还应该将 MemoryField 的大小设置为其子项 _pictureBox 的大小,否则它将无法正确调整以适合其内容。

public class MemoryField : Field {
    public MemoryField(Form parent, int xSize, int ySize) {
        _pictureBox.ClientSize = new Size(xSize, ySize);
        // I removed the setting of Location for the _pictureBox.
        this.Size = _pictureBox.ClientSize; // size container to its wrapped PictureBox
        this.Parent = parent; // not needed
    }
    // ...
}

并将您的创建内循环更改为

for (int x = 0; x < 10; x++) // 10 columns
{
    Field field = new MemoryField(this,
        fieldWidth,
        fieldHeight);
    field.Location = new Point(x * (fieldWidth + 3), 0 + 0 + y * (fieldHeight + 3)); // Set the Location here instead!
    this.Controls.Add(field);
}