Мерцание при перерисовке картинок C#

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by madwort, 17 Apr 2010.

  1. madwort

    madwort New Member

    Joined:
    29 Mar 2010
    Messages:
    8
    Likes Received:
    0
    Reputations:
    0
    Здравствуйте!

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

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

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

    Описание отдельного класса Элемент:
    Code:
    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
        }
    }
    
    Описание действий на форме
    Code:
    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_Click(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
        }
    }
    
     
  2. cheater_man

    cheater_man Member

    Joined:
    13 Nov 2009
    Messages:
    651
    Likes Received:
    44
    Reputations:
    7
    Чувак я тебе же пример показывал как с помощью OnPaint рисовать. Зачем тебе public void Draw(Graphics g) если можно OnPaint'ом обойтись и мерцания небудет ;)
     
  3. BrainDeaD

    BrainDeaD Elder - Старейшина

    Joined:
    9 Jun 2005
    Messages:
    774
    Likes Received:
    292
    Reputations:
    214
    foreach нагружает производительность больше чем for. по этому в designerPanel_Paint используй цикл for. в целом, использование array вместо коллекций может тоже выжать немного скорости. а вообще в критических случаях для работы с графикой лучше подходит directX.
     
  4. Irdis

    Irdis Elder - Старейшина

    Joined:
    6 Feb 2006
    Messages:
    248
    Likes Received:
    52
    Reputations:
    3
    google -> двойная буферизация c sharp
    и будет тебе счастье =)
    ----------------------
    суть в том, что мы рисуем(когда необходимо отрисовать что-либо) на битмэп. А потом, подменяем изображение на контроле на уже готовое.
     
    #4 Irdis, 17 Apr 2010
    Last edited: 17 Apr 2010
  5. Irdis

    Irdis Elder - Старейшина

    Joined:
    6 Feb 2006
    Messages:
    248
    Likes Received:
    52
    Reputations:
    3
    BrainDeaD
    Будет мерцать чуть побыстрее XD
     
  6. cheater_man

    cheater_man Member

    Joined:
    13 Nov 2009
    Messages:
    651
    Likes Received:
    44
    Reputations:
    7
    Двойная буферизация и onPaint, а если чисто двойная буферизация то толку нет. Личный опыт.
     
  7. Irdis

    Irdis Elder - Старейшина

    Joined:
    6 Feb 2006
    Messages:
    248
    Likes Received:
    52
    Reputations:
    3
    cheater_man
    Не совсем так. Не получается потому, что когда вызывается стандартная перерисовка то всё что вы отрисовали сбрасывается на дефолтное изображение. (А это можно обойти)
     
  8. cheater_man

    cheater_man Member

    Joined:
    13 Nov 2009
    Messages:
    651
    Likes Received:
    44
    Reputations:
    7
    Дак блин нужно зафорить.
    Использовать ArrayList, для хранения местоположения каждой картинки:
    Code:
            protected override void OnPaint(PaintEventArgs e)
            {
                base.OnPaint(e);
                for(int i=0; i<Array.Leght;i++)
                {
                  //paint
                }
              }
    
    
    Отрисововал так более 100 компонентов на Form.
    Без мерцания.
    Ну а конечно наилучший метод это ArrayList+IEnumerator+Container+Collection. Идиальный результат получается.
     
  9. madwort

    madwort New Member

    Joined:
    29 Mar 2010
    Messages:
    8
    Likes Received:
    0
    Reputations:
    0
    а как отрисовывать элементы с помощью OnPaint, но только не ан форме, а на панели??