PDA

Просмотр полной версии : Мерцание при перерисовке картинок C#


madwort
17.04.2010, 10:10
Здравствуйте!

Если кто знает, как можно улучшить, буду признателен.

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

Как можно от этого избавиться???

Описание отдельного класса Элемент:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Reflection;

namespace CircuitBuilder
{
class Element
{
const int DEFAULT_WIDTH = 100;
const int DEFAULT_HEIGHT = 26;
Image ElementImage = CircuitBuilder.Properties.Resources.Elem;

public Element(string name, int x, int y)
{
this.Name = name;
this.X = x;
this.Y = y;
this.Width = DEFAULT_WIDTH;
this.Height = DEFAULT_HEIGHT;
}

#region Свойства

public string Name { get; set; }
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }

public Size Size
{
get { return new Size(Width, Height); }
}

public Point Location
{
get { return new Point(X, Y); }
}

#endregion

#region Открытые Методы

public void Draw(Graphics g)
{
g.DrawImage(ElementImage, X, Y, Width, Height);
g.DrawString(Name, SystemFonts.DefaultFont, SystemBrushes.WindowText, new Point(X, Y + Height));
}

#endregion
}
}


Описание действий на форме

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CircuitBuilder
{
public partial class Form1 : Form
{
List<Element> elements = new List<Element>();
Element SelectedElement = null;
Boolean dragging;
Point startDragPoint;
public Form1()
{

InitializeComponent();
}
#region Методы

Element GetItemAt(int x, int y)
{
foreach (Element currElement in elements)
{
if (
currElement.X < x &&
currElement.X + currElement.Width > x &&
currElement.Y < y &&
currElement.Y + currElement.Height > y
)
return currElement;
}
return null;
}

#endregion

#region События меню


private void выходToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}

private void новыйToolStripMenuItem_Click(object sender, EventArgs e)
{
elements.Clear();
designerPanel.Invalidate();
}

private void добавитьЭлементToolStripMenuItem_Cl ick(object sender, EventArgs e)
{
Element element = new Element(" Элемент " + elements.Count.ToString(), 0, 0);
elements.Add(element);
designerPanel.Invalidate();
}

private void designerPanel_Paint(object sender, PaintEventArgs e)
{
foreach (Element element in elements)
element.Draw(e.Graphics);
}

private void designerPanel_MouseDown(object sender, MouseEventArgs e)
{
Element element = GetItemAt(e.X, e.Y);
if (element != null)
{
SelectedElement = element;
dragging = true;
startDragPoint = e.Location;
}
}

private void designerPanel_MouseUp(object sender, MouseEventArgs e)
{
if (dragging)
{
dragging = false;
designerPanel.Invalidate();
}

}

private void designerPanel_MouseMove(object sender, MouseEventArgs e)
{
if (dragging)
{
SelectedElement.X = SelectedElement.Location.X + (e.Location.X - startDragPoint.X);
SelectedElement.Y = SelectedElement.Location.Y + (e.Location.Y - startDragPoint.Y);
designerPanel.Invalidate();
startDragPoint = e.Location;
}
}

#endregion
}
}

cheater_man
17.04.2010, 10:42
Чувак я тебе же пример показывал как с помощью OnPaint рисовать. Зачем тебе public void Draw(Graphics g) если можно OnPaint'ом обойтись и мерцания небудет ;)

BrainDeaD
17.04.2010, 10:49
foreach нагружает производительность больше чем for. по этому в designerPanel_Paint используй цикл for. в целом, использование array вместо коллекций может тоже выжать немного скорости. а вообще в критических случаях для работы с графикой лучше подходит directX.

Irdis
17.04.2010, 11:49
google -> двойная буферизация c sharp
и будет тебе счастье =)
----------------------
суть в том, что мы рисуем(когда необходимо отрисовать что-либо) на битмэп. А потом, подменяем изображение на контроле на уже готовое.

Irdis
17.04.2010, 11:50
BrainDeaD
Будет мерцать чуть побыстрее XD

cheater_man
17.04.2010, 11:55
BrainDeaD
Будет мерцать чуть побыстрее XD
Двойная буферизация и onPaint, а если чисто двойная буферизация то толку нет. Личный опыт.

Irdis
17.04.2010, 11:58
cheater_man
Не совсем так. Не получается потому, что когда вызывается стандартная перерисовка то всё что вы отрисовали сбрасывается на дефолтное изображение. (А это можно обойти)

cheater_man
17.04.2010, 12:22
cheater_man
Не совсем так. Не получается потому, что когда вызывается стандартная перерисовка то всё что вы отрисовали сбрасывается на дефолтное изображение. (А это можно обойти)
Дак блин нужно зафорить.
Использовать ArrayList, для хранения местоположения каждой картинки:

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
for(int i=0; i<Array.Leght;i++)
{
//paint
}
}


Отрисововал так более 100 компонентов на Form.
Без мерцания.
Ну а конечно наилучший метод это ArrayList+IEnumerator+Container+Collection. Идиальный результат получается.

madwort
20.04.2010, 14:11
а как отрисовывать элементы с помощью OnPaint, но только не ан форме, а на панели??