Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Проблемы с перерисовкой графики


Автор: BerdArt 19.9.2008, 16:26
Здравствуйте!
Есть у меня несколько вопросов по рисованию...
1. У меня есть массив, в котором хранятся различные графические объекты (эллипс, прямоугольник, ромб и т.д.). В обработчике Paint PictureBox'а я  перебираю весь этот массив и вызываю  у каждого объекта метод Show. В самом начале пытаюсь удалить прежнее содержимое , но не получается - все остается на прежних местах. Т.е. допустим если я переместил какой-то объект, то он появился на новом месте как объект(т.е. я могу его выделить, удалить и т.п.), но старые тоже остался, но только уже просто в виде фигуры (т.е. его я не могу не схватить, не переместить не удалить). Делаю я это все след. образом:

Код

ShapesContainer shapesList; 
Bitmap bitmap;
Graphics g;

public Form1()
{
    shapesList = new ShapesContainer();  //объект класса в котором храняться все нарисованные фигуры
    bitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
    g = Graphics.FromImage(bitmap);
    SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
.   //.....
}

//.......

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
            
    if (shapesList.Count != 0)
    {
         g.Clear(Color.White);
         shapesList.DrawAll(g);
         pictureBox1.Image = bitmap;
    }
}


2. Если я вот таким образом рисую то у меня загрузка ЦП = 100% и выделение памяти максимальное (1200МБ). Что я делаю не так? 
Кстати, рисует отлично, без всяких глюков и миганий. Если я Graphics возьму непосредственно от PictureBox'a, то появятся миганию, задержи прорисовки и куча подобных глюков. Но проц не загружается так сильно, хотя первая проблема остается в силе.
Код

public Form1()
{
    shapesList = new ShapesContainer();  //объект класса в котором храняться все нарисованные фигуры
    g = pictureBox1.CreateGraphics();
    SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
.   //.....
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
   if (shapesList.Count != 0)
   {
       g.Clear(Color.White);
       shapesList.DrawAll(g);
    }
}


3. Если же я заменю PictureBox Panel'ом, то мигания некорые остаються, хотя и не такие сильные. Но так как похоже на Panel загрузить битмап не получится, то приходиться рисовать на Graphics'е взятом непосредственно от панели. 
Код

public Form1()
{
    shapesList = new ShapesContainer();  //объект класса в котором храняться все нарисованные фигуры
    g = panel1.CreateGraphics();
    SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
.            //.....
}

И опять же первая проблема в силе.

Заранее благодарен.
Суважением, BerdArt

Автор: BerdArt 19.9.2008, 20:13
Все, вопрос решен.
Кстати, хочется отметить, на счет рисования на форме. Встречал в интернете (и на этом форуме, в частности) вопросы по поводу мигания изображения при перерисовки и большой загрузки процессора. Так вот, решение этой проблемы следующее:

Код

ShapesContainer shapesList; 
Bitmap bitmap;
Graphics g;
public Form1()
{
    shapesList = new ShapesContainer();  //объект класса в котором храняться все нарисованные фигуры
    bitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
    g = Graphics.FromImage(bitmap);
    SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
.   //.....
}
//.......
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
            
    if (shapesList.Count != 0)
    {
         g.Clear(Color.White);
         shapesList.DrawAll(g);
         e.Graphics.DrawImage(bitmap,0,0);
    }
}


Немного прокомментирую, точнее отмечу важные моменты:
1. Рисуйте не на контексте устройства (не на самом pictureBox'е), а на битмапе. И только потом закидывайте его в pictureBox.
2. Используйте двойную буферизацию (строка 9).
3. Загружайте битмап не через свойство Image pictureBox'a, а с помощью метода DrawImage (строка 20).
4. Все виртуальное рисование (т.е. на битмапе) можете выполнять где вам удобно. А загружайте в pictureBox только при перерисовки - в событии Paint. Если нужно где-то сделать силовую перерисовку, то вызывайте метод pictureBox1.Invalidate().

Всем успехов!

Автор: Angelius 19.9.2008, 20:35
BerdArt
спасибо за инфу! =)
 на днях пригодится!

Автор: BerdArt 20.9.2008, 11:49
Всегда пожалуйста;)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)