Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Fortlaufenden Graph zeichnen lassen (https://www.delphipraxis.net/80290-fortlaufenden-graph-zeichnen-lassen.html)

ituser 6. Nov 2006 17:56


Fortlaufenden Graph zeichnen lassen
 
Wie der Threadtitel schon sagt suche ich nach einer Möglichkeit, möglichst ohne viel Rechenleistung einen fortlaufenden Graph (wie z.B. im Task Manager bei der CPU-Anzeige) zeichnen zu lassen. Bisher habe ich es mit Canvas auf einem Image versucht, möglicherweise ist meine Idee nicht die beste, denn ich habe, um den Fortlaufeffekt zu verwirklichen, alle bisherigen Pixel einzeln nach links verschieben lassen, sobald der Graph den rechten Rand des Images erreicht. Mein Image hat die ungefähren Maße 200x150 px was ja eigentlich nicht sonderlich groß ist. Selbst bei einem TimerInterval von 1000ms merkt man schon, dass er mit dem Zeichnen nicht ganz nach kommt. Ich möchte jedoch, dass es auch auf schlechteren Rechnern bei größeren Maßen des Images noch flüssig läuft.

Als nächstes habe ich es mit DelphiX probiert, ich dachte, dass das Canvas auf einem DxDraw auch von der Hardware gerendert wird, was aber scheinbar nicht der Fall ist. Die Performance war identisch.

Was käme noch an Möglichkeiten in Frage? Ich habe schon daran gedacht ein TRect aus dem bisherigen Image zu schneiden und eben etwas weiter links im Image zu platzieren, was den gleichen Effekt haben sollte. Allerdings scheitere ich dort an der Ausführung :?
Wie bekomme ich einen bestimmten Inhalt aus einem Image in das Rect? Und ist das denn überhaupt weniger rechenlastig?

Delphi-Quellcode:
  //Timerereignis, sieht mit DelphiX genauso aus, da ich nicht weiß wie ob es eine Funktion für DX gibt um einfache Linien zu zeichnen wie bei Canvas

  if rand=false then ix:=ix+2;

  image1.Canvas.Pen.color:=clred;
  if ix=5 then begin
    image1.canvas.moveto(ix-2,image1.Height);
    image1.Canvas.lineto(ix,image1.Height-trunc(Temperatur*4));
  end else begin
    //Bei erster Zeichnung
    image1.Canvas.MoveTo(ix-2,ypsilon);
    image1.Canvas.LineTo(ix,image1.Height-trunc(Temperatur*4));
    ypsilon:=image1.Height-trunc(Temperatur*4);
  end;

  //Wenn am Rand angekommen, alle linken Pixel ersetzen (bis auf 2px Rand links)
  if (ix>=image1.Width-2) then begin
    for i:=2 to image1.Width do begin
      for j:=0 to image1.Height do begin
          image1.Canvas.Pen.Color:=image1.Canvas.Pixels[i+1,j];
          image1.Canvas.Pixels[i-1,j]:=image1.Canvas.Pixels[i+1,j];
          image1.Canvas.Pen.Color:=image1.Canvas.Pixels[i,j];
          image1.Canvas.Pixels[i-2,j]:=image1.Canvas.Pixels[i,j];
      end;
    end;

    rand:=true;
  end;
Ich wäre euch unglaublich dankbar wenn ihr eine Lösung für mich parat hättet :)
MfG ituser

Cöster 6. Nov 2006 18:04

Re: Fortlaufenden Graph zeichnen lassen
 
Du könntest mit der Methode Draw oder BitBlt einen Bildausschnitt verschieben

xaromz 6. Nov 2006 18:07

Re: Fortlaufenden Graph zeichnen lassen
 
Hallo,

die Lösung lauten MSDN-Library durchsuchenScrollDC.

Gruß
xaromz

ituser 6. Nov 2006 18:09

Re: Fortlaufenden Graph zeichnen lassen
 
Wow, danke für die schnellen Antworten. Ich werde es gleich mal ausprobieren.

ituser 6. Nov 2006 18:30

Re: Fortlaufenden Graph zeichnen lassen
 
Da mich die Syntax etwas verwirrt und ich kein gutes Beispiel gefunden habe scheint es nicht zu funktionieren. Hat einer von euch ein funktionierendes Beispiel? Habe folgendes ausprobiert nach einem Thread hier im Forum.

Delphi-Quellcode:
  image1.Canvas.Pen.color:=clred;
  if ix=5 then begin
    image1.canvas.moveto(ix-2,image1.Height);
    image1.Canvas.lineto(ix,image1.Height-trunc(Temperatur*4));
  end else begin
    image1.Canvas.MoveTo(ix-2,ypsilon);
    image1.Canvas.LineTo(ix,image1.Height-trunc(Temperatur*4));
    ypsilon:=image1.Height-trunc(Temperatur*4);
  end;

  //Wenn am Rand angekommen
  if (ix>=image1.Width-2) then begin
    //Einzelne Pixel Methode
    {for i:=2 to image1.Width do begin
      for j:=0 to image1.Height do begin
          image1.Canvas.Pen.Color:=image1.Canvas.Pixels[i+1,j];
          image1.Canvas.Pixels[i-1,j]:=image1.Canvas.Pixels[i+1,j];
          image1.Canvas.Pen.Color:=image1.Canvas.Pixels[i,j];
          image1.Canvas.Pixels[i-2,j]:=image1.Canvas.Pixels[i,j];
      end;
    end;}

    //Andere
    ScrollRect := image1.BoundsRect;
    ClipRect := image1.BoundsRect;

    ScrollDC(image1.Canvas.Handle, -2, 0, ScrollRect, ClipRect, 0, @UpdateRect);
   
    rand:=true;
  end;
Funktioniert aber leider nicht :-/

Gausi 6. Nov 2006 18:57

Re: Fortlaufenden Graph zeichnen lassen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab das mal mit ner Paintbox und nem temporären Bitmap so gemacht:
Delphi-Quellcode:
tmpbmp.Canvas.FillRect(tmpbmp.Canvas.ClipRect);
tmpbmp.Canvas.CopyRect(
     rect(0,0,Paintbox1.Width-1, Paintbox1.Height),
     Paintbox1.Canvas,
     rect(1,0,Paintbox1.Width, Paintbox1.Height));

tmpbmp.Canvas.MoveTo(Paintbox1.Width-2, OldYPosition);
tmpbmp.Canvas.LineTo(Paintbox1.Width-1, NewYPosition);
BitBlt(Paintbox1.Canvas.handle, 0,  0, tmpbmp.Width, tmpbmp.Height,
       tmpbmp.Canvas.Handle, 0, 0, srccopy);
Was jetzt OldYPosition und NewYPosition genau sind, ist ja egal. Wenn man da nen zufi-generator drumbaut, sieht es z.B. so aus wie in der exe im Anhang

oki 6. Nov 2006 19:09

Re: Fortlaufenden Graph zeichnen lassen
 
Hi ituser,

also bei mir funzt es genau so:

Delphi-Quellcode:
ScrollDC(image1.Canvas.Handle, -2, 0, ScrollRect, ClipRect, 0, @UpdateRect);
Dabei sind alle Rect's die ClientRects meiner Compo. Mit alternativ für UpdateRect = nil klappt es genau so.

Gruß oki

ituser 6. Nov 2006 19:21

Re: Fortlaufenden Graph zeichnen lassen
 
Klappt irgendwie alles nicht so wirklich, wahrscheinlich liegt dann wohl der Fehler in einem anderen Teil der Prozedur, ich poste mal das gesamte Timerereignis... wahrscheinlich hab ich da wieder was vergessen :wall:

@Gausi:

Scheinbar vergesse ich bei deiner Version jedes mal was bestimmtes einzubauen, nur was...

Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
var
  Dezimalwert: byte;
  Spannung, Widerstand, Temperatur: double;
  ScrollRect, ClipRect: TRect;
begin

  {if rand=false then} ix:=ix+2;

  //Einlesen von Daten

  {try
    Dezimalwert:=ADEin;
  except
    dezimalwert:=random(30)+1;
  end;}

  //Zufällige DAten
  dezimalwert:=random(10)+90;


  Spannung:=(DezimalWert/255)*5;
  Widerstand:=Spannung/Ik;
  Temperatur:=25+(sqrt(k1*k1-4*k2+4*k2*(Widerstand/2000))-k1)/(2*k2);

  label5.caption:=inttostr(Dezimalwert);
  label6.caption:=floattostrf(Spannung,fffixed,6,2)+' V';
  label7.caption:=floattostrf(Widerstand,fffixed,6,2)+' Ohm';
  label8.caption:=floattostrf(Temperatur,fffixed,6,2)+' °C';

  image1.Canvas.Pen.color:=clred;
  if ix=5 then begin
    image1.canvas.moveto(ix-2,image1.Height);
    image1.Canvas.lineto(ix,image1.Height-trunc(Temperatur*4));
  end else begin
    image1.Canvas.MoveTo(ix-2,ypsilon);
    image1.Canvas.LineTo(ix,image1.Height-trunc(Temperatur*4));
    ypsilon:=image1.Height-trunc(Temperatur*4);
  end;

  //Wenn am Rand angekommen
  if (ix>=image1.Width-2) then begin
    //Einzelne Pixel Methode
    {for i:=2 to image1.Width do begin
      for j:=0 to image1.Height do begin
          image1.Canvas.Pen.Color:=image1.Canvas.Pixels[i+1,j];
          image1.Canvas.Pixels[i-1,j]:=image1.Canvas.Pixels[i+1,j];
          image1.Canvas.Pen.Color:=image1.Canvas.Pixels[i,j];
          image1.Canvas.Pixels[i-2,j]:=image1.Canvas.Pixels[i,j];
      end;
    end;}

    //Andere
   ScrollRect:=image1.BoundsRect;
   ClipRect:=image1.BoundsRect;
   ScrollDC(image1.Canvas.Handle, -2, 0, ScrollRect, ClipRect, 0, nil);


  end;



end;

runner 12. Nov 2006 19:46

Re: Fortlaufenden Graph zeichnen lassen
 
Schau mal so geht es

Delphi-Quellcode:
  Image1.Canvas.Pen.color := clred;
  if (ix < Image1.Width - 6) then
    begin
      Image1.Canvas.MoveTo(ix - 2, ypsilon);
      Image1.Canvas.LineTo(ix, trunc(Temperatur));
      ypsilon := trunc(Temperatur);
    end

      //Wenn am Rand angekommen
  else
    begin
      ScrollRect := Image1.BoundsRect;
      ClipRect := Image1.BoundsRect;
      ScrollDC(Image1.Canvas.Handle, -2, 0, ScrollRect, ClipRect, 0, nil);
      Image1.Canvas.MoveTo(Image1.Width - 6, ypsilon);
      Image1.Canvas.LineTo(Image1.Width - 4, trunc(Temperatur));
      ypsilon := trunc(Temperatur);
    end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:19 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz