![]() |
Probleme beim Umstellen von Array zu Stringlist
Liste der Anhänge anzeigen (Anzahl: 1)
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:
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:
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.
Delphi-Quellcode:
Sieht jemand eventuell, wo der Fehler liegt?
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; Habe zum besseren Verständnis mal das Projekt angehängt. Vielen Dank BAMatze |
Re: Probleme beim Umstellen von Array zu Stringlist
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 ![]() [edit]
Delphi-Quellcode:
Verzögert den Programmstart um 4 Sekunden.
procedure TForm1.FormShow(Sender: TObject);
begin ControlerBoard := TControlerBoard.create; ControlerBoard.Initialising; sleep(4000); end; Grüße Klaus |
Re: Probleme beim Umstellen von Array zu Stringlist
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:
[/Edit]
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; [Edit2] Fehler steckt in Folgendem Quellcode, was ich aber nicht verstehe, da dieser bisher noch nie Probleme gemacht hat:
Delphi-Quellcode:
[/Edit]
//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; |
Re: Probleme beim Umstellen von Array zu Stringlist
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 |
Re: Probleme beim Umstellen von Array zu Stringlist
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] |
Re: Probleme beim Umstellen von Array zu Stringlist
.. was ich bei mir noch auskommentiert habe ist:
Delphi-Quellcode:
Ansonsten ließ sich das Programm nicht kompilieren.
//Application.MainFormOnTaskbar := True;
Auf die Form2 (die mit dem Fadenkreuz) kann ich ohne Problem wechseln. Zitat:
Blockieren diese eventuell den Refresh? Grüße Klaus |
Re: Probleme beim Umstellen von Array zu Stringlist
Zitat:
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. |
Re: Probleme beim Umstellen von Array zu Stringlist
Also ich lasse derzeit über einen separaten Thread Daten von einem Analogen Eingang einer ControlerBoardkarte im 50ms-Takt schreiben. Habe das in meinem letzten
![]() [Edit] Der Hinweis mit dem Thread war glaube ich das richtig. Der Thread sieht NOCH wie folgt aus: Thread-Quellcode (Auszug):
Delphi-Quellcode:
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) :wall: . Werde ich jetzt mal umbauen.
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; [/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? |
Re: Probleme beim Umstellen von Array zu Stringlist
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.) |
Re: Probleme beim Umstellen von Array zu Stringlist
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] |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:11 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz