Avatar billede czix Nybegynder
29. april 2008 - 07:42 Der er 17 kommentarer og
1 løsning

OnPaint - metoden

Hej alle sammen

I forbindelse med en graf, jeg er ved at lave, bruger jeg OnPaint til at tegne. Grafen gør faktisk det den skal, men grafen "hænger" ikke sammen. Dvs. at den slette foregående streg, den har lavet. Så den minder mere om en probe, end og en hel støbt graf.

                using (Pen Graphpen = new Pen(Color.Black))
                {
                    time++;
                    float sample = _samples[_samples.Count - 1];
                    if (time > ClientSize.Width)
                    {
                        time = 0;
                        g.Clear(Color.Transparent);
                    }
                    float signal = ClientSize.Height - sample;
                    g.DrawLine(Graphpen, time, signal, ptime, psignal);

                    psignal = signal;
                    ptime = time;
                }

Nogle der kan løse dette problem?
Avatar billede aaberg Nybegynder
29. april 2008 - 08:19 #1
Du tegner jo bare en streg i ovenstående kode! Hver gang OnPaint metoden bliver kørt, bliver kontrollen tegnet forfra, dvs. alt som var der fra før bliver slettet. Derfor bliver du nød til at tegne hele grafen i OnPaint metoden.
Avatar billede czix Nybegynder
29. april 2008 - 11:38 #2
Ressourcemæssig kræver det vel meget? Eneste løsning er vel at hente værdierne fra _samples-arrayet, og kører det hele i en for-løkke ?
Avatar billede aaberg Nybegynder
29. april 2008 - 13:59 #3
Du kan godt fortælle kontrollen hvad den skal gentegne ved at kalde Invalidate(Rectangle) eller Invalidate(Region). Men da bliver du nød til at tage højde for at kontrollen nogle gange vil gentegne hele sig selv, f.eks. hvis du minimere dit vindue og maksimere det igen. Det nemmeste er at tegne alt på nyt, hver gang grafen skal opdateres. Det er i hvert fald sådan jeg ville starte, så kan man altid effektivisere det senere, med at tilføje noget mere avanceret logik.

Så svaret er vel ja, tegn alle værdierne i det array hver gang ved hjælp af en for-løkke.
Avatar billede czix Nybegynder
29. april 2008 - 14:23 #4
Okay, det lyder fornuftigt.

Men grafen skal ikke minimeres eller maksimeres, idet det er i fast "ramme". Så de problemer er jeg fri for. Hvordan/hvor implementeres Invalidate(Region)?
Avatar billede bvli Praktikant
29. april 2008 - 16:32 #5
Spørgsmålet er vel, om det kan betale sig at regne på region/clip i stedet for bare at tegne det hele igen?

Du har dine samples i et array af floats ikk'?

Hva' med:

g.DrawLines(pen, samples);

?

/B
Avatar billede aaberg Nybegynder
30. april 2008 - 11:29 #6
Det er ikke bare når du minimere og maksimere den prøver at tegne igen, det er også hvis du dragger et andet vindue over din form, da vil den prøve at tegne igen.

Invalidate metoden er en metode som ligger på Control klassen, det vil sige at alle kontroller og forme har denne metode. Når du kalder Invalidate() bliver OnPaint automatisk kørt. Hvis du køre invalidate med en Region som parameter, bliver ClipRegion på Graphics objektet sat før OnPaint kaldes, hvilket betyder at Graphics objectet kun kan tegne inden for denne Region.

Jeg vil dog stadig råde dig til at tegne hele kontrollen på nyt hver gang, så hellere begynde at rode med Regions og Rectangles når der skal fartstriber på din graf!
Avatar billede czix Nybegynder
02. maj 2008 - 10:38 #7
#aaberg80
Som du nok fornemmer, er jeg helt ny på området, men jeg forstår godt, hvor du vil hen.

Det som bvli foreslår, virker som en god ide, men Drawlines tager et array af Points som argument, så derfor er det ikke sådan lige til.
Avatar billede aaberg Nybegynder
02. maj 2008 - 14:42 #8
Prøv at se om dette her virker:

using (Pen Graphpen = new Pen(Color.Black))
{
    List<PointF> points = new List<PointF>();
    time = 0;

    foreach (float sample in _samples)
    {
        if (time > this.ClientSize.Width)
            time = 0;

        points.Add(new PointF(time, ClientSize.Height - sample));
        time++;
    }

    g.DrawLines(Graphpen, points.ToArray());
}
Avatar billede czix Nybegynder
02. maj 2008 - 15:11 #9
Får følgende fejl:

Collection was modified; enumeration operation may not execute. (Sker i linjen foreach (float sample in _samples) ). Kan umiddelbart ikke se, hvad der er i vejen.


Følgende virker af og til, men går ned, hvis jeg ikke ligger +1 til _samples.Count.

                using (Pen Graphpen = new Pen(Color.Black))
                {
                    PointF[] points = new PointF[_samples.Count + 1];

                    for (int idx = 0; idx < _samples.Count; ++idx)
                    {
                        points[idx] = new PointF(idx, (ClientSize.Height - _samples[idx]));
                    }

                    if (points != null)
                    { g.DrawLines(Graphpen, points); }
                }
Avatar billede czix Nybegynder
02. maj 2008 - 15:30 #10
Skyldes nok at _samples er et objekt af Collection, som den er nedarvet fra.
Avatar billede aaberg Nybegynder
02. maj 2008 - 20:05 #11
Denne fejl opstår hvis din collection bliver ændret på imens den er i en foreach-løkke. For eksempel hvis der bliver tilføjet items imens den er i løkken.

prøv:

using (Pen Graphpen = new Pen(Color.Black))
{
    int sampleCount = _samles.Count;
    PointF[] points = new PointF[sampleCount];

    for (int idx = 0; idx < sampleCount; ++idx)
    {
        points[idx] = new PointF(idx, (ClientSize.Height - _samples[idx]));
    }

    if (points != null)
    {
        g.DrawLines(Graphpen, points);
    }
}

Kan det passe at _samples collectionen bliver fyldt op fra en anden tråd?
Avatar billede czix Nybegynder
03. maj 2008 - 14:25 #12
Ja, den bliver fyldt op ved hjælpe af en tråd. Det lykkes faktisk nu (tildels), men hvis jeg fylder _samples collection op langsom (>100 ms pr. sample), så chrasher den, og skriver "Parameter not valid" på g.DrawLines(Graphpen, points);

Hvad kan det skyldes?
Avatar billede czix Nybegynder
03. maj 2008 - 14:33 #13
Den vil selvfølgelig ikke tegne, hvis points kun indeholder et element.

            if (_samples.Count > 0)
            {
                using (Pen Graphpen = new Pen(Color.Black))
                {
                    int sampleCount = _samples.Count;
                    PointF[] points = new PointF[sampleCount];

                    for (int idx = 0; idx < sampleCount; ++idx)
                    {
                        points[idx] = new PointF(idx, (ClientSize.Height - _samples[idx]));
                    }

                    if (points != null && sampleCount != 1)
                    {
                        g.DrawLines(Graphpen, points);
                    }
                }
Avatar billede czix Nybegynder
10. maj 2008 - 11:00 #14
svar
Avatar billede aaberg Nybegynder
10. maj 2008 - 21:44 #15
du mener altså ikke at du fik noget hjælp siden du tager alle pointsne selv?
Avatar billede czix Nybegynder
11. maj 2008 - 18:09 #16
Første gang jeg prøver pointsystemet, så skal lige fatte det (Kan også ses på nogle af de andre tråde, jeg har oprettet). Men jo, jeg er meget taknemlig for hjælpen.
Avatar billede czix Nybegynder
11. maj 2008 - 18:10 #17
Så du må meget gerne svare, hvis du vil have pointene.
Avatar billede aaberg Nybegynder
11. maj 2008 - 20:56 #18
Man skal jo lære det :-)

Tak for pointsne
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester