29. april 2008 - 07:42Der 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);
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.
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.
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)?
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!
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); } }
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?
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);
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.
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.