Squeak.ru - шаблоны программирования

Динамически созданная проблема рендеринга PictureBox

Конечная цель — несколько играбельная игра на память. В настоящее время я застрял на проблеме рендеринга. У меня есть следующие классы:

Поле, которое является абстрактным 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 из Fields (каждый из которых содержит PictureBox размером 100x100 пикселей). Я делаю это почти успешно, так как мое второе поле отображается неправильно: Проблема рендеринга с размером поля 100x100 пикселей

Единственное, что я обнаружил, что работает (полностью устраняет проблему), это увеличение поля (например, 150 пикселей). С другой стороны, уменьшение его (например, 50 пикселей) делает проблему еще больше:

Проблема рендеринга с размером поля 50x50 пикселей


Возможно, полезная информация и то, что я пробовал:

  • Моя основная форма AutoSize = true; с AutoSizeMode = GrowAndShrink;
  • Моя основная форма (изначально) не содержит никаких компонентов, кроме menuStrip и label
  • Я попытался изменить свойство PictureBox.Image, но это не помогло.
  • Я попытался создать сетку только с PictureBox элементами управления (не используя Field в качестве оболочки PictureBox), и это действительно сработало.
  • Я попытался поместить labelTimer в эту «проблемную область», которая действительно устраняет проблему в зависимости от того, где именно я ее поместил. (поскольку позиционирование поля зависит от положения и высоты labelTimer )
  • Я попытался перезапустить визуальную студию 2017, не помогло.

Конечно, я мог бы просто изменить размер на 150 пикселей и двигаться дальше, но мне действительно любопытно узнать, в чем корень этой проблемы. Спасибо!

10.11.2019

  • Я не уверен, что понимаю связь с labelTimer, возникает ли проблема без этого элемента управления labelTimer? Если это так, я предлагаю вам удалить его из примера кода и снимков, чтобы сделать его менее загроможденным! Но, возможно, это связано. 10.11.2019
  • Зачем ты это делаешь: _pictureBox.Parent = parent;? Не делай этого. PictureBox должен обрабатываться UserControl. Кстати, UserControl уже знает своего родителя, это [UC].ParentForm (унаследовано от ContainerControl). По крайней мере, установите _PictureBox.BringToFront();. Но вы не должны, на самом деле. 10.11.2019
  • Я думал, что это хирагана в картинках, пока не присмотрелся поближе :) это, вероятно, не имеет ничего общего с вашим пользовательским элементом управления, это еще один элемент управления, скрывающий часть материала, отображаемого с более низким z-порядком. Попробуйте создать все снизу вверх, справа налево, чтобы скрыть это, или определить, что это такое, и удалить это (labelTimer?), кроме этого, рассмотрите Field как производное от PictureBox (подкласс его) - на одну глубину меньше в вашем контроле иерархия. 10.11.2019
  • ИМО ненужная абстракция здесь. Поместите Pictureboxes прямо внутрь TableLayoutPanel и покончите с этим. 10.11.2019
  • Свойство Size элемента управления UserControl не задано. Это единственное, что вы видите, остальные тоже слишком большие, но перекрываются элементами управления PictureBox. 10.11.2019
  • Всем спасибо за предложения! Основная проблема, действительно, заключалась в том, чтобы установить размер и местоположение для _pictureBox и не установить ни один из них для Field (как было предложено @hans-passant и описано в выбранном ответе). Я также удалил .Parent = parent, так как он не нужен (предложено @jimi). Теперь мне осталось рассмотреть TableLayoutPanel и/или вывести Field из PictureBox вместо того, чтобы оборачивать его. Спасибо еще раз! 11.11.2019

Ответы:


1

Самый простой способ решить проблему — это то, что вы уже пробовали, — прямое использование 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 и их подкомпонентов. Вы не должны устанавливать Location каждого _pictureBox относительно его родителя MemoryField, а скорее изменять Location MemoryField относительно его родителя Form.

Вы также должны установить размер вашего 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);
}
10.11.2019
  • Отличный ответ! Исправляет мою ситуацию, предлагает лучшее общее решение и объясняет все, что я не совсем понял ранее. Благодарю вас! 11.11.2019
  • Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...