Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Мерцание при перерисовке картинок C# (https://forum.antichat.xyz/showthread.php?t=196872)

madwort 17.04.2010 10:10

Мерцание при перерисовке картинок C#
 
Здравствуйте!

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

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

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

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

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_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
    }
}


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

Цитата:

Сообщение от Irdis
BrainDeaD
Будет мерцать чуть побыстрее XD

Двойная буферизация и onPaint, а если чисто двойная буферизация то толку нет. Личный опыт.

Irdis 17.04.2010 11:58

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

cheater_man 17.04.2010 12:22

Цитата:

Сообщение от Irdis
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, но только не ан форме, а на панели??


Время: 06:35