Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Fero 28. 08. 2014, 10:54:17

Název: C# PictureBox Draw
Přispěvatel: Fero 28. 08. 2014, 10:54:17
Nazdar ľudkovia!

K veci, riešim realtime vykreslovanie (plot) dat z RS232 do GUI (Visual Studio - C#). V GUI mam PictureBox("pDraw), vykreslovanie "Invalidate" je robene cez Timer(), kazdych 20ms (50 Hz). Data ktore vykreslujem su ulozene v List a ukladaju sa sem z RS232. Problem je, ze po istom case ak je program spusteny, zacne byt vykreslovanie strasne oneskorene, t.j. spravim nejaku vonkajsiu akciu, tato pride cez RS232 do GUI, a GUI to vykresli az o niekolko neskor.

Kod vyzera nasledovne:

Kód: [Vybrat]
        Graphics bmg;
        Bitmap bm;
        List<Point> pointList_X = new List<Point>();

        ...
private void pDraw_Paint(object sender, PaintEventArgs e)
        {
            if (bm == null)
            {
                bm = new Bitmap(iTotalWidth, pDraw.Size.Height);
                bmg = Graphics.FromImage(bm);
                bmg.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
                bmg.Clear(Color.White);
            }
            Render();
            e.Graphics.DrawImage(bm, 0, 0);
        }

        void Render()
        {
            bmg.Clear(Color.White);

            // Draw line to screen.
            bmg.DrawLine(Line, XY_s, XY_e);

            int pplistX = pointList_X.Count;

            if (pointList_X.Count > 2)
            {
                int count = 1;
                foreach (var element in pointList_X)
                {
                    bmg.DrawLine(Pens.Red, pointList_X[count - 1], pointList_X[count]);

                    if (count == (pplistX - 1)) break;
                    else count += 1;
                }
            }
        }
        ...
        private void rTimer_Draw(object sender, EventArgs e)
        {
            pDraw.Invalidate();
        }

Prijem dat je spraveny cez interrupt, data su tu zapisovane do listu.
Kód: [Vybrat]
void sPort_Event_DataReceived(byte data)
        {   
            if (this.InvokeRequired)
            {
                this.Invoke(new DataReceivedDelegate(sPort_Event_DataReceived), new Object[] { data });
            }
            else
            {
                sDecode.setValues(data);
                sDecode.ProcessData();

                if (sDecode.isReady() == 0x01)
                {
                    if (sDecode.retCommand() == 4) { pointList_X.Add(new Point(cnt, (sDecode.retData() / 100))); }
   
                    if(cnt > pDraw.Width) {
                        cnt = 0;
                        pointList_X.Clear();
                    }
                        cnt += 10; 
                }
                sDecode.flushData();
            }
        }

Prijem dat je spraveny na 40Hz, typu Master-slave. Diky za kazdy napad.
M.

Název: Re:C# PictureBox Draw
Přispěvatel: Bla 28. 08. 2014, 11:53:19
Nechce se mi to do detailu prohlížet, nehodí se mi to teď, ale tak logicky Dežo! Logicky!
Zakomentuj plnění listboxu a začni si do toho data generovat pomocí random, tím zjistíš, ve které části ten problém je.
Až uvidíš, jestli to je v první nebo druhé funkci, tak zase zakomentuj jednu část.
Jak jsem řekl, nechce se mi to studovat, ale nejspíš ti někde roste datový objekt.
Objekt o velikosti řekněme 1MB dat se nechová nikterak svižně.
Název: Re:C# PictureBox Draw
Přispěvatel: gamer 28. 08. 2014, 12:12:27
V C# nedělám, ale myslím si, že místo Invalidate() bys měl volat Refresh(), to Invalidate totiž nic nepřekresluje, jen to nacpe jako event do fronty, že by se to mělo udělat někdy později:
http://blogs.msdn.com/b/subhagpo/archive/2005/02/22/378098.aspx
Název: Re:C# PictureBox Draw
Přispěvatel: Fero 28. 08. 2014, 14:49:59
Par hodin debuggovania a... Vykreslovanie bolo spravne, chyba bola v trocha nestastnej implementacii prijmu dat z RS232, data sa tam hromadili a hromadili, a vykreslovanie fungovalo spravne, len vykreslovalo stare data... diky chalani :)
mozete lock/delete

F.