AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Probleme beim Umstellen von Array zu Stringlist
Thema durchsuchen
Ansicht
Themen-Optionen

Probleme beim Umstellen von Array zu Stringlist

Ein Thema von BAMatze · begonnen am 14. Sep 2009 · letzter Beitrag vom 14. Sep 2009
Antwort Antwort
Seite 1 von 2  1 2      
BAMatze

Registriert seit: 18. Aug 2008
Ort: Berlin
759 Beiträge
 
Turbo Delphi für Win32
 
#1

Probleme beim Umstellen von Array zu Stringlist

  Alt 14. Sep 2009, 08:28
Hallo aus einem mir noch nicht nachvollziehbaren Grund bremst sich meine eigene Klasse nach der Umstellung der Klasse von einem festen Array auf ein TStringList, komplett aus, so dass man das Programm nicht mehr benutzen kann (Cursor ändert sich durch Windows in crHourGlass nicht durch das Programm)- passiert gleich beim Starten.

Hier mal die Klasse:

Delphi-Quellcode:
Type TOszilloskopKanal = class
  
  private
    FsLDaten: TStringList; // <-- Hier war vorher ein array of double
    FadExtremaWert: array[0..4] of double;
    FdMaxWert, FdMinWert: double;
    FbAbfragen: boolean;
    FiIdent: integer;
    FsName: string;
    FKanalColor, FBackgroundColor: TColor;
    FOnChangeEingang: TOnChangeEingangEvent;
    procedure SetYWert(dWert: double);
    procedure SetName(sWert: string);
    procedure SetKanalFarbe(cWert: TColor);
    function GetYWert(Index: integer): double;
    function GetName: string;
    function GetKanalFarbe: TColor;
    function GetIdent: integer;
    function GetCountEingangswerte: integer;
    function GetMax: double;
    function GetMin: double;
  protected
    procedure doChangeEingang;
  published
    property OnChangeEingang: TOnChangeEingangEvent read FOnChangeEingang write FOnChangeEingang;
  public
    constructor create(Number: integer); reintroduce;
    destructor destroy; override;
    property EingangY: double write SetYWert;
    property IdentNumber: integer read GetIdent;
    property AusgangY[Index: integer]: double read GetYWert;
    property Name: string read GetName write SetName;
    property KanalColor: TColor read GetKanalFarbe write SetKanalFarbe;
    property CountEingangsWerte: integer read GetCountEingangswerte;
    property Max: double read GetMax;
    property Min: double read GetMin;
end;

implementation

constructor TOszilloskopKanal.Create(Number: integer);
var i: integer;
begin
  inherited create;
  FiIdent := Number;
  FsName := 'Signal '+ inttostr(Number);
  FKanalColor := clblue;
  FsLDaten := TStringList.Create;
  FsLDaten.Add('0');
  FdMaxWert := 0;
  FdMinWert := 0;
end;

destructor TOszilloskopKanal.Destroy;
begin
  FsLDaten.Free;
  inherited destroy;
end;

// Es werden immer nur die letzen Werte gesetzt
procedure TOszilloskopKanal.SetYWert(dWert: double);
begin
  FsLDaten.Add(floattostr(dWert));
  //Extremas überprüfen und ggf neu setzen
  if dWert > FdMaxWert then FdMaxWert := dWert;
  if dWert < FdMinWert then FdMinWert := dWert;
  doChangeEingang;
end;

// Getter und Setter wurden entfernt, um den Text hier möglichst kurz zu halten

procedure TOszilloskopKanal.doChangeEingang;
begin
  if Assigned(FOnChangeEingang) then FOnChangeEingang(Self, FiIdent);
end;

end.
Da ich eventuell noch vermute, dass die übergeordnete Klasse der Verursacher des Problems ist, hier noch mal auszüge, die die Schnittstellen in der höheren Klasse darstellen:

Delphi-Quellcode:
constructor TOszilloskop.create(AOwner: TComponent; CountChannel: Integer);
var i, j: integer;
begin
  inherited create(AOwner);
  Controlstyle := Controlstyle - [csAcceptsControls]; // Der Componente wird nicht erlaubt
                                                      // andere Componenten aufzunehmen,
                                                      // als die, die durch den Programmierer
                                                      // hier einprogrammiert werden.
  //Initialisierung
  SetLength(FSignal, CountChannel);
  for i := 0 to CountChannel-1 do
    begin
      FSignal[i] := TOszilloskopKanal.create(i+1);
      j := i;
      if j >= 5 then repeat j := j-5; until (j < 5);
      case j of
      0 : FSignal[i].KanalColor := clmaroon;
      1 : FSignal[i].KanalColor := clblue;
      2 : FSignal[i].KanalColor := clgreen;
      3 : FSignal[i].KanalColor := clyellow;
      4 : FSignal[i].KanalColor := clred;
      else FSignal[i].KanalColor := clwhite;
      end;
      FSignal[0].OnChangeEingang := FOnSignalEingang;

  FDarstellungsBitmap := TBitmap.Create;
  FDarstellungsBitmap.Width := FiDisplayWidth;
  FDarstellungsBitmap.Height := FiDisplayHeight;

end;

destructor TOszilloskop.Destroy;
var i: integer;
begin
  // Freigabe
  for i := 0 to Length(FSignal)-1 do FSignal[i].Free;
  SetLength(FSignal,0);
  inherited destroy;
end;

// Wenn im Eingang ein Signal anliegt, wird die höhere Klasse darüber informiert und (soll) das Bild für den Kanal neu zeichnen!!
procedure TOszilloskop.FOnSignalEingang(Sender: TObject; const IdentNumber: integer);
var i: integer;
    TempBitmap: TBitmap;
// zu jedem FSignal gehört ein FBitmap, in welchem der Graph, welcher im FSignal gespeichert sein soll, darstellt wird.
begin
  GetRange;
  Maske_erstellen;
  TempBitmap := TBitmap.Create;
  TempBitmap.Height := FiDisplayHeight;
  if FSignal[IdentNumber].CountEingangsWerte < FiDisplayWidth then
    begin
      TempBitmap.Width := FSignal[IdentNumber].CountEingangsWerte;
      TempBitmap.Canvas.CopyRect(rect(0,0,FSignal[IdentNumber].CountEingangsWerte-1,FiDisplayHeight),FBitmap[IdentNumber-1].Canvas,rect(0,0,FSignal[IdentNumber].CountEingangsWerte-1,FiDisplayHeight));
      //TempBitmap.Assign(FBitmap[IdentNumber-1]);
      TempBitmap.Canvas.Pen.Color := FCtransparentColor;
      TempBitmap.Canvas.MoveTo(TempBitmap.Width, 0);
      TempBitmap.Canvas.LineTo(TempBitmap.Width, FiDisplayHeight);
      TempBitmap.Canvas.Pen.Color := FSignal[IdentNumber-1].KanalColor;
      TempBitmap.Canvas.MoveTo(TempBitmap.Width-1, FiDisplayHeight-5 - round((FSignal[IdentNumber-1].AusgangY[FSignal[IdentNumber-1].CountEingangswerte-2]- FdDisplayMin)*FdDisplayStrech));
      TempBitmap.Canvas.LineTo(TempBitmap.Width, FiDisplayHeight-5 - round((FSignal[IdentNumber-1].AusgangY[FSignal[IdentNumber-1].CountEingangswerte-1]- FdDisplayMin)*FdDisplayStrech));
      FBitmap[IdentNumber].Width := FSignal[IdentNumber].CountEingangsWerte;
      FBitmap[IdentNumber].Assign(TempBitmap);
    end
  else
    begin
      TempBitmap.Width := FiDisplayWidth;
    end;
  TempBitmap.Free;
  for I := 0 to Length(FSignal)-1 do InitBitmap(i+1);
  FPB_Display.Refresh;
end;
Sieht jemand eventuell, wo der Fehler liegt?
Habe zum besseren Verständnis mal das Projekt angehängt.

Vielen Dank
BAMatze
Angehängte Dateien
Dateityp: zip teilprojekt_oszi_983.zip (1.014,1 KB, 2x aufgerufen)
2. Account Sero
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.755 Beiträge
 
Delphi 10.4 Sydney
 
#2

Re: Probleme beim Umstellen von Array zu Stringlist

  Alt 14. Sep 2009, 08:56
Guten Morgen,

ich wieß nicht ob das Problem daran liegt,
aber warum nutzt Du zum (zwischen)speichern von double
Werten eine StringList?
Wenn Du die Werte zeichnen willst, musst Du sie auch wieder
konvertieren oder?

Wäre eine TList mit double Einträgen hier nicht sinnvoller?


[edit]
Delphi-Quellcode:
procedure TForm1.FormShow(Sender: TObject);
begin
  ControlerBoard := TControlerBoard.create;
  ControlerBoard.Initialising;
  sleep(4000);
end;
Verzögert den Programmstart um 4 Sekunden.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
BAMatze

Registriert seit: 18. Aug 2008
Ort: Berlin
759 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Probleme beim Umstellen von Array zu Stringlist

  Alt 14. Sep 2009, 09:14
Hallo @Klaus das mit der TList schaue ich mir gleich mal an, kannte ich einfach noch nicht. Ziel für mich ist es, dass ich vom Start des Programmes bis zur Terminierung alle Daten im Speicher behalte. Die bisherige Lösung über ein Array (dieses Array hatte die Größe der Breite vom Darstellungsbildschirm) führte zum Datenverlust aller Werte außerhalb des Darstellungsbildschirmes.
Bei der Verwendung von Array muss ich mich außerdem immer um die Vergrößerung des Feldes selber kümmern, was nachteilhaft ist, wie ich finde (ständig müssen Arrays erstellt, kopiert und bearbeitet werden) nachteilhaft ist, wenn ich bei einer Liste (wie z.B. TStringList) einfach nur ein Add ausführen muss.
Die Zeitverzögerung ist mir bewusst, die hat sich nur eingeschlichen, weil ich es aus einem großen Projekt zur einfacheren Bearbeitung ausgelagert hab. Aber daran liegt der Fehler nicht, da ich das bei mir über 10sek hab laufen lassen und nichts wirklich passierte. Die Nachrichtenschleife des Projektes arbeitet irgenwie nicht und das Programm läd (anscheinend) nicht fertig.

BAMatze

[Edit1] Der Fehler konnte insofern schon eingegrenzt werden, dass beim auskommentieren folgender Zeile in der Oberklasse:
Delphi-Quellcode:
procedure TOszilloskop.FOnSignalEingang(Sender: TObject; const IdentNumber: integer);
var i: integer;
    TempBitmap: TBitmap;
begin
  GetRange;
  Maske_erstellen;
  TempBitmap := TBitmap.Create;
  TempBitmap.Height := FiDisplayHeight;
  if FSignal[IdentNumber].CountEingangsWerte < FiDisplayWidth then
    begin
      TempBitmap.Width := FSignal[IdentNumber].CountEingangsWerte;
      TempBitmap.Canvas.CopyRect(rect(0,0,FSignal[IdentNumber].CountEingangsWerte-1,FiDisplayHeight),FBitmap[IdentNumber-1].Canvas,rect(0,0,FSignal[IdentNumber].CountEingangsWerte-1,FiDisplayHeight));
      //TempBitmap.Assign(FBitmap[IdentNumber-1]);
      TempBitmap.Canvas.Pen.Color := FCtransparentColor;
      TempBitmap.Canvas.MoveTo(TempBitmap.Width, 0);
      TempBitmap.Canvas.LineTo(TempBitmap.Width, FiDisplayHeight);
      TempBitmap.Canvas.Pen.Color := FSignal[IdentNumber-1].KanalColor;
      TempBitmap.Canvas.MoveTo(TempBitmap.Width-1, FiDisplayHeight-5 - round((FSignal[IdentNumber-1].AusgangY[FSignal[IdentNumber-1].CountEingangswerte-2]- FdDisplayMin)*FdDisplayStrech));
      TempBitmap.Canvas.LineTo(TempBitmap.Width, FiDisplayHeight-5 - round((FSignal[IdentNumber-1].AusgangY[FSignal[IdentNumber-1].CountEingangswerte-1]- FdDisplayMin)*FdDisplayStrech));
      FBitmap[IdentNumber].Width := FSignal[IdentNumber].CountEingangsWerte;
      FBitmap[IdentNumber].Assign(TempBitmap);
    end
  else
    begin
      TempBitmap.Width := FiDisplayWidth;
    end;
  TempBitmap.Free;
  for I := 0 to Length(FSignal)-1 do InitBitmap(i+1);
  //FPB_Display.Refresh; // <-- Hier scheint es ein Problem zu geben. Wenn auskommentiert, ist Problem gelöst aber es gibt keine Darstellung (was natürlich logisch ist, weil die Paintbox nicht gezeichnet wird!)
end;
[/Edit]
[Edit2] Fehler steckt in Folgendem Quellcode, was ich aber nicht verstehe, da dieser bisher noch nie Probleme gemacht hat:
Delphi-Quellcode:
//Quellcodeteil aus der NewPaint-procedure in Oberklasse
for i := 0 to Length(FCB_Layer)-1 do
    begin
      if FCB_Layer[i].Checked then transparentBlt(FDarstellungsBitmap.Canvas.Handle, 0, 0, FDarstellungsBitmap.width, FDarstellungsBitmap.Height,
      Fbitmap[i+1].Canvas.Handle, 0, 0, Fbitmap[i+1].Width, Fbitmap[i+1].Height, FCtransparentColor);
    end;
[/Edit]
2. Account Sero
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.755 Beiträge
 
Delphi 10.4 Sydney
 
#4

Re: Probleme beim Umstellen von Array zu Stringlist

  Alt 14. Sep 2009, 09:20
Hallo BAMatze,

habe gerade dein Edit gelesen.

Bei mir startet das Projekt ohne Verzögerung wenn ich die 4 Sekunden
Sleep auskommentiere.

Ob es daran liegt, das hier das Programm auf einem DualCore Rechner läuft?

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
BAMatze

Registriert seit: 18. Aug 2008
Ort: Berlin
759 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: Probleme beim Umstellen von Array zu Stringlist

  Alt 14. Sep 2009, 09:24
Läuft bei dir der Darstellungsbildschirm auf der Form2? kannst du auf diesen wechseln? bei mir freezt das nämlich alles ein

[Edit] auch ohne das sleep(4000); ändert sich bei mir leider nichts, muss wohl an dem DualCoreRehner liegen.[/Edit]
2. Account Sero
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.755 Beiträge
 
Delphi 10.4 Sydney
 
#6

Re: Probleme beim Umstellen von Array zu Stringlist

  Alt 14. Sep 2009, 09:30
.. was ich bei mir noch auskommentiert habe ist:
 //Application.MainFormOnTaskbar := True; Ansonsten ließ sich das Programm nicht kompilieren.

Auf die Form2 (die mit dem Fadenkreuz) kann ich ohne Problem wechseln.

Zitat:
[Edit2] Fehler steckt in Folgendem Quellcode, was ich aber nicht verstehe, da dieser bisher noch nie Probleme gemacht hat:
Greifen mehrere Threads auf die "Paintbox" zu?
Blockieren diese eventuell den Refresh?

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#7

Re: Probleme beim Umstellen von Array zu Stringlist

  Alt 14. Sep 2009, 09:38
Zitat von BAMatze:
Ziel für mich ist es, dass ich vom Start des Programmes bis zur Terminierung alle Daten im Speicher behalte.
Wie hoch ist die Frequenz mit der du neue Werte bekommst? Ich frage, weil es dann schon mächtig fix passieren kann dass du ein extrem unhandliches Listchen vor dir hast. Konzeptionell würde ich hier eher vorschlagen wirklich nur die Daten die zur Anzeige gebraucht werden vorzuhalten, und alte Daten blockweise in ein File zu werfen.

Das könnte z.B. so ausschauen, dass du ein Array mit 2*Bildbreite nimmst, und sobald du [Bildbreite] neue Daten hinten angepappt hast, schreibst du die davor stehenden [Bildbreite] Daten weg. Ausserdem ist es mit einem Array bei sequenziellen Datenströmen nicht unbedingt ein ewiges herumkopiere, solange du eines fester Länge hast. Stichwort: Ringpuffer.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
BAMatze

Registriert seit: 18. Aug 2008
Ort: Berlin
759 Beiträge
 
Turbo Delphi für Win32
 
#8

Re: Probleme beim Umstellen von Array zu Stringlist

  Alt 14. Sep 2009, 10:11
Also ich lasse derzeit über einen separaten Thread Daten von einem Analogen Eingang einer ControlerBoardkarte im 50ms-Takt schreiben. Habe das in meinem letzten Thread wie folgt gelöst und es funktioniert auch jetzt noch, wenn ich die Forschleife in der NewPaint-Procedure auskommentiere.

[Edit] Der Hinweis mit dem Thread war glaube ich das richtig. Der Thread sieht NOCH wie folgt aus:

Thread-Quellcode (Auszug):
Delphi-Quellcode:
procedure TControlCardControlThread.Execute;
var c, iIndex: integer;
    //TempTisch: TTischInfo;
    //Punkte, Geschwindigkeiten, Beschleunigungen: array[1..3] of double = [0,0,0];
    
begin
  repeat
    c := GetTickCount;

    //bReaktion := boolKombination(4);
  
    Synchronize(Sync);
  
    c := {interval}50 - (GetTickCount - c);
    if c > 0 then Sleep(c);
  until Terminated;
end;

procedure TControlCardControlThread.Sync;
var
  i: Integer;
begin
  Form3.ProgressBar1.Position := ReadanalogChannel(1);
  Form3.ProgressBar2.Position := ReadanalogChannel(2);
  for i := 1 to 5 do
    begin
      if ReaddigitalChannel(i) then
        begin
          case i of
          1: Form3.CheckBox9.Checked := true;
          2: Form3.CheckBox10.Checked := true;
          3: Form3.CheckBox11.Checked := true;
          4: Form3.CheckBox12.Checked := true;
          5: Form3.CheckBox13.Checked := true;
          end;
        end
      else
        begin
          case i of
          1: Form3.CheckBox9.Checked := false;
          2: Form3.CheckBox10.Checked := false;
          3: Form3.CheckBox11.Checked := false;
          4: Form3.CheckBox12.Checked := false;
          5: Form3.CheckBox13.Checked := false;
          end;
        end;

    end;
  Form2.EingangsSignal[0] := ReadanalogChannel(1);
  if ReadDigitalChannel(5) then Form2.EingangsSignal[1] := 256
  else Form2.EingangsSignal[1] := 0;
end;
Greife dämlicher Weise direkt auf visuelle Komponenten zu, was ja nicht wirklich glücklich ist und (verständlicher Weise) zu Fehlern führt. Wenn ich die Zugriffe auf die visuellen Komponenten auskommentiere, funktioniert alles (auch die NewPaint-Procedure) . Werde ich jetzt mal umbauen.
[/Edit]

@Medium ist ein guter Hinweis, das mit dem Ringpuffer, werde ich mich jetzt wohl doch mal mit beschäfftigen müssen und dann wie du vorschlägst die nicht benötigten Daten in eine File schreiben.
Aber hab da noch eine Frage, wenn ich bis zum Anfang zurück scrollen will, dauert das ja sicherlich mit dem Laden der Daten etwas oder ist die Ladezeit (ca 500-600 Punkte werden dargestellt) maginal/trivial?
2. Account Sero
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#9

Re: Probleme beim Umstellen von Array zu Stringlist

  Alt 14. Sep 2009, 11:30
Wenn du die Werte binär wegspeicherst (also bloß kein Textfile und FloatToStr oder so Gelümmel ), kannst du die benötigte Position im FileStream nachher recht fix mit Seek(Pos*SizeOf(WerteTyp)) anspringen. Das Auslesen selber ist dann eher nur noch eine Formalie - wichtig ist nur dass du nicht aufwendig vorher rumsuchen musst.

Du musst evtl. mit der Größe des Teilpuffers der weggespeichert wird etwas herumspielen, bis du eine Größe hast die keine Ruckler verursacht - bei 50ms Updatezeiten könnte man das evtl. ab und an merken. Ich denke mal Blockgrößen von 1024 bis 4096 Bytes sollten im geeigneten Rahmen liegen. (Es müssen ja nicht [Bildbreite] Werte sein. Wenn dein Puffer [Blocksize]+[Bildbreite] ist, nimmst du den hinteren Teil zum Zeichnen, und nach [Blocksize] Inputs den vorderen Teil wegschreiben, bevor dessen erstes Element wieder überschrieben wird.)
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
BAMatze

Registriert seit: 18. Aug 2008
Ort: Berlin
759 Beiträge
 
Turbo Delphi für Win32
 
#10

Re: Probleme beim Umstellen von Array zu Stringlist

  Alt 14. Sep 2009, 12:49
Cool schonmal ein paar Informationen, die mir die Arbeit erleichtern werden. Habe ebend über eine Art kleine DB nachgedacht, wo ich nen Index als Position verwende (ala 1, 2,3; 2, 1,4 und so weiter (1. Zahl Index 2. Zahl doubleWert) so dass ich über die Bildlaufleiste Feststellen kann, dass ich z.B. die Werte 300 - 799 laden muss. Aber hast recht kann natürlich auch über die Speicherposition dies direkt ansprechen.
Jetzt muss ich aber noch eine Nachlässigkeit zugeben, habe bisher immer alles in eine Textfile (ini oder txt) gespeichert, weil das immer das einfachste fßür mich war. Werde mich also erstmal mit binär-Dateien auseinandersetzen müssen. Denke aber mal Binärdatei wird sicherlich heißen Zahl in Dualcode (Basis 2) speichern.

BAMatze

[Edit] Die Datei braucht übrigens nur für den Zeitpunkt der Messung zur Verfügung zu stehen. Spätestens bei Beenden des Programms sollte alles aufgeräumt werden und die Daten können verworfen werden, da anhand des Graphen der Bediener entscheidet, ob alles seine Richtigkeit hatte. (Nur eine Ergänzung weil ich hier irgendwas mit einem Stream lese in der SuFu) Könnte man das in dem Fall auch in einen Stream packen? [/Edit]
2. Account Sero
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:49 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