Warum wird Memo1.Lines gefüllt ?

Für Fehler in Lazarus, um diese von anderen verifizieren zu lassen.
pluto
Lazarusforum e. V.
Beiträge: 7180
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Warum wird Memo1.Lines gefüllt ?

Beitrag von pluto »

Hallo,
ich habe die Frage schon hier gestellt:
http://www.delphipraxis.net/post800151.html#800151
und ich stelle sie noch einmal hier, weil ich gestern was seltsames raußgefunden habe.

Es wird einfach Memo1.Lines gefüllt und nicht Listbox1.items wie es eigentlich sein sollte.

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  PlayListeManger:=TPlaylistenManger.Create;
  PlayListeManger.PlayListItems:=Listbox1.items;
end;


Schreibe ich Memo1.Lines hängt sich das Programm auf.
Mein Ziel ist es:

Ich möchte den TPlaylistenManger.PlayListItems mit der Listbox1.Items verbinden.
So das sie beide die gleiche Bedeutung haben. Was aber leider nicht der Fall ist.

Jetzt rufe ich TPlaylistenManger.LoadFromFile auf die sieht so aus:

Code: Alles auswählen

procedure TPlaylistenManger.LoadFromFile(const aFileName: String = '');
var
  i:integer;
begin
  InitPlaylist(ExtractFileName(aFileName), fPlayliste);
  if assigned(Playliste) then
  begin
 
    Playliste.OhneExt:=OhneExt;
    Playliste.PlayListItems := PlayListItems;
    Playliste.LoadFromFile(aFileName);
 
//    writeln(PlayListItems.text);
 
  //  PlayListItems.Assign(Playliste.PlayListItems);
 
    _ext:=Playliste.ext;
  end
  else
    ShowMessage('Unbekannter Playlistentyp!');
end;


Mein Ziel ist es das Listbox1.items weiter gereicht wird bis zur TPlayListM3U.PlayListItems Variable.

Unter Delphi habe ich getestet klappt das auch zu 50%.
Allerdings gibt es unter Delphi eine AV sobald ich TPlaylistenManger.PlayListItems abfragen möchte, ich vermute sie ist wieder LEER. Aber warum ?


ich habe es mal hochgeladen, damit ihr es euch besser vorstellen könnt.
Schaut euch mal bitte dieses Projekt an, und sagt mir was bei euch Passiert.
(Bevor hier es Kompliert müsst hier noch unter SpeedButton1Click die Playliste ändern, die geladen werden soll)

VIELEN DANK !!!

Edit1: Kann das sein das Lazarus noch nicht alle Komponenten Installisiert hat bei From1.OnCreate ?
Dateianhänge
playlisten.zip
(7.8 KiB) 70-mal heruntergeladen
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7180
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

so Muetze1 aus der DP hat mir bestätigt das es ein Lazarus BUG ist.
hier seine Erklärung:
Das Problem liegt einfach nur daran, dass du die im PlaylistenManager hinterlegte Instanz der Items nicht beim InitPlaylist() - also anlegen der Instanz - deren Eigenschaft weiterreichst. Wenn du dies dort machst, brauchst du diese Zuweisung nicht mehr.

Grundlegend habe ich debuggt mit Lazarus und Lazarus hat ein Problem mit dem AddObject() mit dem Info. Anscheinend meint er, dass die TInfo Instanz nicht mehr existiert. Der Debugger ist leider keine Hilfe und in den Komponentenquelltext komme ich nicht reindebuggt. Grundlegend scheint es wirklich ein Lazarus Problem zu sein. Warum ist eine andere Frage.


Meine Frage ist jetzt, kommt es bei euch auch zu diesen Fehler ?
Sobald ich die Zuweisung verschiebe z.b. in einem onButtonClick rein mache, dann geht das so wie ich es mir vorgestellt hatte.
MFG
Michael Springwald

ulhau
Beiträge: 65
Registriert: Sa 27. Okt 2007, 13:27
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Seebergen

Beitrag von ulhau »

Hallo Mimi ähm Pluto !

Zuerst, ja es gibt bei mir auch eine Fehlermeldung nach der anderen und wenn sich Muetze1 schon das Gehirn verrenkt hat dann sieht es schon ziemlich schlecht aus. Aber ein paar Fragen hab ich trotzdem.

1. Was macht eigentlich das Startprogramm? (Ich hab nur mit WinXP getestet)
2. Wie kommt ListBox1 an die Items die der PlaylisteManger.PlayListItems im Form1.Create ereignis zugewiesen werden?

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  PlayListeManger:=TPlaylistenManger.Create;
  PlayListeManger.PlayListItems:=Listbox1.items;
end;


3. Muss eine leere ListBox nicht vor einem Zugriff geschützt werden wenn im onClick Ereignis Aktionen ausgelöst werden die mit leeren oder unvollständigen Einträgen nichts anzufangen wissen?

Code: Alles auswählen

procedure TForm1.ListBox1Click(Sender: TObject);
var
  info:TInfo;
begin
  If Listbox1.Items.Count > 0 Then
  begin
     info:=PlayListeManger.GetPlayListenItem(ListBox1.ItemIndex);
 
     Memo1.Lines.Add(info.FileName);
     Memo1.Lines.Add(info.Kommentar);
     Memo1.Lines.Add('--------------------------------');
  end;
end;


4. Muss denn nicht erst was in der ListBox1 drinstehen ehe die Playlist korrekt gefüllt werden kann? (Was ja dann funktioniert wenn es im Button.Click Ereignis gemacht wird oder zum beispiel bei Form1.FormShow).

Code: Alles auswählen

procedure TForm1.FormShow(Sender: TObject);
begin
  If ListeIst = False Then
    begin
      PlayListeManger := TPlaylistenManger.Create;
      PlayListeManger.PlayListItems := Listbox1.items;
      PlayListeManger.LoadFromFile(StartPath + 'oldies.m3u');
      ListeIst := True;
      SpeedButton3.Enabled := True;
    end;
end;


Na ja, wie gesagt, ich hab da blos unter Windows ein wenig getestet und hänge das ergebnis mal an. Ach ja, starte das Programm mal extern und nicht aus der IDE(Lazarus).

Es war halt ein Versuch. Tschüssss
Dateianhänge
PlaylistenProjekt.zip
(99.25 KiB) 65-mal heruntergeladen

pluto
Lazarusforum e. V.
Beiträge: 7180
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

zu 1
Ich wollte beim Starten gleich eine Playliste laden. In die Listbox

zu 2
PlayListeManger.PlayListItems:=Listbox1.items;
Das ist ein Pointer, eigentlich müssten jetzt wenn ich auf PlayListeManger.PlayListItems das gleiche sein wenn ich aufistbox1.items; zugreife.

zu 3
Eigentlich ja, aber ist es ja nur ein Test Programm gewesen.

zu 4
Eigentlich nicht, ich müsste auch eine Leer Listbox füllen können. oder was genau meinst du damit ?

Es war halt ein Versuch.
Vielen Dank, das du dich damit befasst hast.

wenn sich Muetze1 schon das Gehirn verrenkt
Wir sind beide zum gleichen Schluss gekommen, das es sich hierbei um einen Fehler handelt.

Da ich noch eine ältere FPC Version habe, dachte ich das es daran liegen könnte.
Eine neuer habe ich aus Faulheit noch nicht, aufgespielt.

Welche FPC Version hast du denn ?

Edit00
Ich sehe gerade das du die Zuweisung bei onShow machst, mir ging es allerdings darum die Zuweisung bei onCreate zu machen......

Edit001

Code: Alles auswählen

StartPath := ExtractFilePath(application.exename);

Wenn du das exe Verzeichnis haben, möchtest, dann mache es lieber so, ich habe mal gelesen das ParamStr(0) nicht immer was enthält.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10500
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

pluto hat geschrieben:zu 2
PlayListeManger.PlayListItems:=Listbox1.items;
Das ist ein Pointer, eigentlich müssten jetzt wenn ich auf PlayListeManger.PlayListItems das gleiche sein wenn ich aufistbox1.items; zugreife.


Das ist sicher keine Pointer zuweisung sondern führt ein Assign aus

Code: Alles auswählen

property Items: TStrings read FItems write SetItems;
 
procedure TCustomListBox.SetItems(Value : TStrings);
begin
  if (Value <> FItems) then begin
//DebugLn('[TCustomListBox.SetItems] A FItems=',FItems.ClassName,' Value=',Value.ClassName);
    LockSelectionChange;
    FItems.Assign(Value);
    UnlockSelectionChange;
  end;
end;

pluto
Lazarusforum e. V.
Beiträge: 7180
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

warum ? Das verstehe ich jetzt nicht:
Klasse1, Klass2:TSTrings
Klasse1:=TStringlist.Create;
Klasse1:=Klass2

Jetzt müsste doch Klasse2 auf Klasse 1 Zeigen, wie bei mir oben.
das fItems.assigend hatte ich auch schon rauß gemacht zwischen durch
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10500
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Tja, kann sein, wenn du das so gemacht hast. Hatte mir den Source nicht angeschaut.
Ist einfach etwas ungewöhnlich. Bei TMemo.Items oder TListbox.Items ist die Zuweisung ein Assign.

pluto
Lazarusforum e. V.
Beiträge: 7180
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

ach ? du meinst es könnte an den verwendeten Komponenten liegen ?
Wenn ich jetzt z.b. meiner Klasse eine Stringlist zuweise ohne Assign zu verwenden, das es doch intern genutzt wird ? muss ich mal nach sehen.....

Aber wie erklärst du dir das, wenn ich das gleich mache aber nur woanders z.b. beim ButtonClick ?
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10500
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Ich meine gar nix. Aber waghalsig ist es schon, in OnCreate den Pointer auf die ListBox.Items abzuholen.
Wenn z.B. die Listbox aus irgendeinem Grund ihre Items zerstört und neu created, zeigt dein Pointer ins Nirvana.
Ich sage nicht, dass es nicht geht, aber mir wäre unwohl dabei.

ulhau
Beiträge: 65
Registriert: Sa 27. Okt 2007, 13:27
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Seebergen

Beitrag von ulhau »

UiUiUi ganz schön kompliziert. Geht das auch mal ganz einfach und altmodisch?

Tja, vieleicht geht hier was was nicht gehen dürfte.

Code: Alles auswählen

PlaylisteManger.PlayListItems:=Listbox1.Items


Die Eigenschaft TListBox.Items enthält die Strings, die im Listenfeld angezeigt werden.
Und wenn die Listbox aber leer ist dann ist halt nix da.

Oder wo werden die Strings eingelesen.

Oder musst du dir hier auch eine eigene Listbox basteln.

Oder gibts noch eine andere möglichkeit die Sache zu verbinden?

pluto
Lazarusforum e. V.
Beiträge: 7180
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Die TPlaylistManger Klasse hat eine Methode die sich um das einlesen kümmern sollte: LoadFromFile.

Die entscheidet welche Klasse Genommen werden muss:
TPlaylistM3U oder TPlaylistPLS.

warum sollte PlaylisteManger.PlayListItems:=Listbox1.Items nicht gehen ?
das ist eine normale Zuweisung. Beide Variablen müssten jetzt auf die gleicher Pointer Adresse Zeigen. So spare ich mir unötige Events.

Aber es hat ja den anscheind das es jetzt klappt. Nach dem ich das aus OnCreate verschoben habe. Jetzt möchte ich halt nur noch wissen warum das so ist.
MFG
Michael Springwald

ulhau
Beiträge: 65
Registriert: Sa 27. Okt 2007, 13:27
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Seebergen

Beitrag von ulhau »

Na dann ist doch gut. Wenn's geht dann geht's doch, dann ist doch nicht's falsch.

Dann musst Du halt blos noch herausfinden welche unterschiede zwischen den einzelnen ereignissen bestehen also create u.s.w.

Na dann Tschüsss und erzähl halt das Rätsel mal weiter wenn es gelöst ist.

pluto
Lazarusforum e. V.
Beiträge: 7180
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

du bist lustig *G*....

Ich weiß wann onCreate ausgelöst wird.
Sobald das Formular erstellt wurde, also nach dem alle Komponenten auf den Formular sind...

Ich bin mir sehr sicher das es sich um einen Lazarus-Bug handeln muss....
könnte mir jemand von euch sagen, ob es so einen BUG schon eingetragen gibt im Bug-Tracker ?
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10500
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

pluto hat geschrieben:warum sollte PlaylisteManger.PlayListItems:=Listbox1.Items nicht gehen ?
das ist eine normale Zuweisung. Beide Variablen müssten jetzt auf die gleicher Pointer Adresse Zeigen.


Ja, trotzdem spielst du mit dem Feuer.
Die Listbox verplichtet sich dir gegenüber nicht, diesen Pointer stabil zu halten.
Falls die Listbox beschliesst, die Items neu zu createn, guckst du in die Röhre.
Wenn du "Glück" hast, kriegst du dann eine Zugriffsverletzung. Sonst kann die Sache auch einfach aus dem Ruder laufen.

Ich hab dir mal ein Bespiel gemacht:

Code: Alles auswählen

{ TTest }
 
  TTest=class
  private
   fLines:TStrings;
  protected
    procedure ClearDeep;
  public
   constructor Create;
   property Lines:TStrings read fLines write fLines;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
var Test:TTest;
St:TStrings;
begin
 Test:=TTest.create;
 St:=Test.fLines; //Waghalsig den Pointer holen, im Vertrauen, dass sich dieser nicht aendert
 St.Add('testa'); //Hurra klappt!
 Test.ClearDeep//Eine Prozedur der Komponente aufrufen
 Test.Lines.Add('testc')//Kein Problem, Komponente funzt weiterhin
 Memo1.lines.add(Test.Lines.Text);
 St.Add('testb'); //Geht in die Hose
 Memo1.Lines.Add(St.Text);
end;
 
{ TTest }
 
procedure TTest.ClearDeep; //Es ist das gute Recht der Komponente folgendes zu tun:
var temp:TStringList;
begin
 fLines.free;
 temp:=TStringList.create//Sicherstellen, dass es nicht "zufaellig" doch klappt
 fLines:=TStringList.Create; //Die Komponente funzt weiterhin, nur der Pointer ist futsch.
 temp.free;
end;
 
constructor TTest.Create;
begin
  fLines:=TStringList.Create;
end;

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6217
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Beitrag von af0815 »

pluto hat geschrieben:warum sollte PlaylisteManger.PlayListItems:=Listbox1.Items nicht gehen ?
das ist eine normale Zuweisung. Beide Variablen müssten jetzt auf die gleicher Pointer Adresse Zeigen. So spare ich mir unötige Events.

Wer sagt das es Pointer sind ? Ich sehe hier zwei Klassen, die Eigenschaften haben. Zu weist eine Eigenschaft der anderen zu. Weites ist eine Eigenschaft oder Methode keine Variable.

Wo ist hier klar, das mit Pointern und ihren Eigenschaften gearbeitet wird. Nirgends.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten