Рейтинг:
0
Kornfeld Eliyahu Peter
Прекратите все, что обесценивает - это причина мерцания. Вы перекрашиваете всю панель с чрезвычайной частотой...
Ваша вторая проблема заключается в том, как вы пытаетесь справиться с графическим объектом...Вы создаете изображение и из него графический объект, а затем назначаете его обратно на панель в качестве фона...Это полная трата времени, ИМХО...
Попробуйте нарисовать непосредственно графический объект панели!!!
public partial class Form1 : Form
{
Graphics g;
bool mouse_down = false;
public Form1 ( )
{
InitializeComponent ( );
}
private void panel1_MouseDown ( object sender, MouseEventArgs e )
{
mouse_down = true;
}
private void panel1_MouseMove ( object sender, MouseEventArgs e )
{
if ( mouse_down )
{
g.FillRectangle ( Brushes.Black, new Rectangle ( e.X, e.Y, 5, 5 ) );
}
}
private void panel1_MouseUp ( object sender, MouseEventArgs e )
{
mouse_down = false;
}
private void Form1_Load ( object sender, EventArgs e )
{
g = panel1.CreateGraphics ( );
}
}
[РЕДАКТИРОВАТЬ]
Как правильно сказал Сергей, мое решение очень неуклюже в том смысле, что оно решает только непосредственную проблему представленного кода, но не решает реальную проблему - упорное рисование!
Чтобы объяснить эту проблему здесь очень краткое объяснение того, как работает живопись в Windows:
Ваше окно (панель или любой другой элемент управления, являющийся его частью) рисует само себя - это означает, что не Windows OS рисует эти красивые границы и кнопки на вашем окне, а само окно (и его части) знает, как его рисовать...
Но! Когда (и какая часть) синхронизируется Windows с помощью отправки сообщения paint (WM_PAINT) в каждое окно в соответствии с изменениями его состояния и/или видимости. Например, окно стало видимым (закрыв окно поверх него), и Windows отправляет ему сообщение paint, чтобы уведомить его о событии.
Теперь на вашем окне (панели) есть много рисунков, созданных из событий мыши, но что произойдет, если какое-то другое окно перекрывает (скрывает) часть вашего окна? Эта скрытая часть будет потеряна, и когда ваше окно станет видимым во второй раз - и вы получите сообщение краски - никто не будет знать, как его воссоздать...
Должно быть два основных метода для сохранения знаний о том, как воссоздать чертеж:
1. Запишите все картины, которые вы сделали в своего рода очередь, и после получения сообщения paint используйте эту очередь, чтобы снова нарисовать все картины. Это может быть очень полезно для более сложной программы рисования, которая может обрабатывать каждый нарисованный "объект" (например, круг, прямоугольник или линию) индивидуально...
2. Создайте теневую копию - отключенную от главного окна - вашей картины и скопируйте ее обратно после сообщения paint
Я покажу образец для второго подхода (так как это гораздо больше образца) сейчас:
public partial class Form1 : Form
{
Graphics g;
Graphics g_shadow;
Bitmap bmp;
bool mouse_down = false;
public Form1 ( )
{
InitializeComponent ( );
}
private void panel1_MouseDown ( object sender, MouseEventArgs e )
{
mouse_down = true;
}
private void panel1_MouseMove ( object sender, MouseEventArgs e )
{
if ( mouse_down )
{
// draw both to the panel and to the shadow image
g.FillRectangle ( Brushes.Black, new Rectangle ( e.X, e.Y, 5, 5 ) );
g_shadow.FillRectangle ( Brushes.Black, new Rectangle ( e.X, e.Y, 5, 5 ) );
}
}
private void panel1_MouseUp ( object sender, MouseEventArgs e )
{
mouse_down = false;
}
private void Form1_Load ( object sender, EventArgs e )
{
g = panel1.CreateGraphics ( );
// here create a second Graphics object that will paint to an non-visible shadow image
bmp = new Bitmap ( panel1.Width, panel1.Height );
g_shadow = Graphics.FromImage ( bmp );
}
private void panel1_Paint ( object sender, PaintEventArgs e )
{
// copy the shadow image to the main panel
e.Graphics.DrawImageUnscaled ( bmp, e.ClipRectangle );
}
}
Sergey Alexandrovich Kryukov
Мне очень жаль, но это просто неправильное решение. Он не сохранит результаты этих штрихов, потому что вы не используете OnPaint. Если вы используете его, вы должны были указать этот важный момент.
На самом деле, Invalidate не является источником мерцания, если вы используете его правильно. Можно сделать недействительной только часть сцены. А как насчет CreateGraphics? Да, вы можете использовать его, но гораздо более сложным способом. Один из способов таков: вы можете использовать оба экземпляра графики: один вы создаете, а другой передаете в OnPaint. Первый используется для рисования "здесь и сейчас", другой - для рендеринга после аннулирования. Это всего лишь идея. Но! простое рисование всего этого только в OnPaint будет работать, возможно, с более низкой производительностью.
Вы пробовали сами создать приложение для рисования? С первого взгляда то, что вы описали, не сработает. Это может сработать, если вы добавите гораздо больше деталей, но вы этого не сделали.
Спасибо за понимание.
—СА
Kornfeld Eliyahu Peter
Я не собирался создавать приложение paint, чтобы ОП только указывал на основные проблемы, которые я видел.
Вы правы насчет не сохранения части. Это решение не будет перекрашивать старую часть (скажем, перекрытую другим окном), а только с этого момента...Однако оригинал ОП тоже этого не сделал...
Вы также верно говорите о том, что Invalidate сам по себе не будет проблемой, но в том, как OP использует его...
Sergey Alexandrovich Kryukov
Я понимаю, но тебе нужно что-то с этим делать. Если кто-то непосредственно следует вашему коду, это не сработает.
Если вы понимаете, как исправить это так, как это было бы применимо к реальному приложению рисования, вам просто нужно это сделать.
—СА
Kornfeld Eliyahu Peter
Небольшое обновление - я взял этот код и создал проект, и Сюрприз-сюрприз...Это работает. Это работает в смысле сохранения рисунка. Несмотря на то, что вы (и, честно говоря, я тоже :-)) думали, что панель внутри формы сохраняет рисунки поперек изменения размера, перекрытия и перемещения...
Мой последний проект GUI был написан на C++ с использованием простых вызовов API, и от этого это как-то неожиданно...Мне придется рассмотреть его в деталях...
Sergey Alexandrovich Kryukov
Пожалуйста, поймите меня правильно. Если это для вас сюрприз, вы не должны публиковать его, пока не поймете, как он работает во всех деталях. И тогда вы должны предоставить всю информацию, а не только то, что вы написали. Как написано, это не сработает; это должно быть что-то другое. Пожалуйста, скажите мне: вы используете OnPaint? обработайте событие краски.
Если нет, то я не уверен, что он сохраняет рисунок. Сделайте это: переместите окно влево или вправо, за экран, чтобы покрыть место, где были штрихи. Затем переместите его назад, чтобы сделать штрихи видимыми. Они сохранились? Но если это так, то вы не предоставили существенную часть кода. Вам действительно нужно поместить эти стоксы в некоторые данные, сохранить эти данные и использовать эти данные для рендеринга при недействительности. Не обесценивая себя, вы скрываете проблему, но не решаете ее.
—СА
Kornfeld Eliyahu Peter
Я не стремлюсь доказать свою правоту или вашу неправоту - я только делюсь информацией (пока по крупицам)...
Я также ищу ваш вклад (чтобы сделать мою жизнь проще: -)), чтобы собрать как можно больше, когда (надеюсь, завтра) У меня будет время, чтобы изучить и обновить решение...
Sergey Alexandrovich Kryukov
Извините, но в данном случае этого недостаточно. Это даже не комментарий, это "решение", поэтому вам нужно быть более осторожным. Вам действительно нужно объяснить, как это может работать, и, возможно, добавить больше кода.
Таким образом, "исследовать и обновить решение" будет действительно хорошей идеей.
Пожалуйста, держите меня в курсе тоже.
—СА
Kornfeld Eliyahu Peter
Я расширил решение...
Sergey Alexandrovich Kryukov
Теперь есть объяснение, с объяснением фрагмента кода, но вы изменили реализацию и сделали ее ближе к OP.
Интересно: вы наблюдаете мерцание (я думаю, нет; это правда? ОП что-то напутал).
Тем не менее, есть проблема с этим: использование изображения в значительной степени избыточно, потому что используется двойная буферизация. Я думаю, вы видели мой ответ, где я объясняю это. Скажите, пожалуйста: используете ли вы изображение полного размера клиента (как-то), меньшего (что могло бы как-то оправдать использование image: performance)?
Так или иначе, я проголосовал за это решение, просто чтобы исключить свой первоначальный голос 1...
Спасибо,
—СА
Kornfeld Eliyahu Peter
Я сделал свое решение ближе к ОПУ, чтобы он лучше понял - в конце концов, это для него...
Конечно, никакого мерцания вообще нет - я думаю, что первоначальное мерцание произошло из-за того, что ОП инициировал полный размер недействительности с каждым рисунком...
Об изображении...Я создаю изображение того же размера, что и панель, используемая для рисования, но копирую только соответствующую часть в соответствии с недействительной областью, поэтому в очень редких случаях оно будет охватывать большие части рисунка...
Я проверил использование памяти и производительность и обнаружил, что все в порядке...
Спасибо Вам за ваше голосование и еще больше за ваши комментарии...
Также позвольте мне поздравить вас с MVP этого года (тоже) - молодец!
Sergey Alexandrovich Kryukov
- Спасибо, Питер. Мои поздравления для вас, слишком.
Я хотел увидеть ваше подтверждение. Как я и думал, никакого мерцания нет.
Однако использование изображения клиентского размера является чисто избыточным — оно просто удваивает функциональность двойной буферизации. Если вы включите его, мое решение, основанное на прямом рисовании OnPaint, также будет без мерцания и проще.
—СА
Kornfeld Eliyahu Peter
Спасибо - мой MVP был для меня сюрпризом, так как я вижу здесь людей с гораздо большими знаниями и способностью помочь...Я проскользнул туда случайно, но постараюсь изо всех сил оправдать ожидания...
О Мерцании изображений. Я уверен, что вы правы насчет двойной буферизации и комбинации OnPaint...Я думаю, что теперь два ответа (ваш и мой с исправлением) могут дать ОПУ всю картину, что-то узнать и выбрать свой путь к решению...
Sergey Alexandrovich Kryukov
Могу я объяснить, что вы делаете?
Некоторые говорят: "я использую эту и эту технику для кузнечной работы, но кувалда слишком тяжелая". Вы отвечаете: "просто снимите кувалду с процедуры, она будет выглядеть точно так же". (Или используйте деревянную кувалду.) Все в порядке, только металлическая часть не поддается ковке... :-)
—СА
BillWoodruff
+5, чтобы противостоять глупому голосованию вниз, и сказать, что мне нравится, как вы толкаете конверт здесь, и наслаждаться спиной и пеной между вами и Сергеем. Результат этого, я уверен, будет чем-то полезным для других людей в будущем.
Kornfeld Eliyahu Peter
Спасибо...
Sergey Alexandrovich Kryukov
Пожалуйста, смотрите мое обновление к моему ответу, после [EDIT], где я объясняю больше, особенно первую ссылку. Это может дать вам ключ к разгадке.
—СА