Графика над картинкой не отображается, и если она есть, они мерцают перед исчезновением

Я работаю над приложением Windows Form и когда я использую System.Drawing.Graphics в верхней части графического окна графика либо не появляется, либо появляется только на мгновение перед тем, как исчезнуть.

Это код, который я использую для установки картинки (это упрощенная версия и все еще демонстрирует поведение)

private void showGraphic()
{
    pictureBox1.Invalidate();
    System.Drawing.Graphics graphics = this.pictureBox1.CreateGraphics();
    SolidBrush semiTransBrush = new SolidBrush(Color.FromArgb(128, 0, 0, 255));
    System.Drawing.Rectangle rect = new System.Drawing.Rectangle(100,100, 50, 50);

    graphics.FillEllipse(semiTransBrush, rect);
}

private void button1_Click(object sender, EventArgs e)
{
    showGraphic();
}

Настройки для окна рисунка - это просто настройки по умолчанию для изображения из файла, объявленного на панели свойств.

Я смог решить эту проблему с помощью таймера, который запускался кнопкой, а затем выполнял графический рисунок перед тем, как остановиться, однако это казалось ужасным решением, и я хотел сделать это лучше, если он существует, так как это может привести к в отсутствии переносимости на старые компьютеры.

заранее спасибо

2 ответа

Решение

Вам необходимо зарегистрировать обработчик для метода Paint в PictureBox и сделать рисование в этом методе. (Примечание: используйте объект Graphics, переданный через параметр PaintEventArgs.) Это гарантирует, что в любой момент, когда PictureBox будет перерисован, ваш код для рисования также будет работать. В противном случае вы просто рисуете что-то, что будет обновлено по любой из причин.

Как только вы зарегистрируетесь в событии Paint, в любое время, когда вы захотите перекрасить, вызовите Invalidate() в PictureBox, и ваш код рисования запустится. Вы можете отслеживать, следует ли рисовать оверлейную графику с помощью закрытой логической переменной-члена.

Когда вы звоните pictureBox1.Invalidate() он ставит в очередь сообщение о том, что графическое окно должно быть нарисовано. Перед обработкой этого сообщения вы рисуете эллипс поверх текущей картинки. Затем цикл обработки сообщений обрабатывает сообщение рисования от недействительного и затем перерисовывает себя (что стирает ваше изображение)

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

  1. Создайте новое растровое изображение размером с картинку.
  2. Рисовать на растровом изображении.
  3. Установите растровое изображение в качестве изображения.

Например:

// create a new bitmap and create graphics from it
var bitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
var graphics = System.Drawing.Graphics.FromImage(bitmap);

// draw on bitmap
SolidBrush semiTransBrush = new SolidBrush(Color.FromArgb(128, 0, 0, 255));
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(100,100, 50, 50);
graphics.FillEllipse(semiTransBrush, rect);

// set bitmap as the picturebox's image
pictureBox1.Image = bitmap;

С помощью приведенного выше кода вы можете нарисовать все один раз, и он переживет события перерисовки.

Другие вопросы по тегам