Selbsteliminierung führt zu SIGSEGV [gelöst]

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
frawi
Beiträge: 3
Registriert: Mo 27. Dez 2010, 10:56

Selbsteliminierung führt zu SIGSEGV [gelöst]

Beitrag von frawi »

Hallo zusammen,

ich möchte in einer tScrollbox mehrere tFrames untereinander auflisten. Jedes tFrame besitzt einen eigenen DELETE-Button, über den es selbst gelöscht werden kann. Klicke ich auf den DELETE-Button, nachdem ich mehrere tFrames erzeugt habe, bedankt sich das Programm mit einem SIGSEGV !? Ich vermute, dass ich irgendwelche oop-Regeln verletzte, weiss aber nicht, wie ich das korrekt lösen muss.

das grundsätzliche Löschen eines tFrames funktioniert. Ich habe das ausprobiert mit:

Code: Alles auswählen

sbJobs     ist die tScrollBox
aJobFrame  ist meine tFrame-Klasse (tFrameJobDetail)
 
  if (sbJobs.Components[0] is tFrameJobDetail) then begin
    aJobFrame := (sbJobs.Components[0] as tFrameJobDetail);
    aJobFrame.Free;
  end;
Es funktioniert nur dann nicht, wenn ich es über den DELETE-Button auf dem tFrame durchführe. Kann mir jemand sagen, woran das liegt. Wie macht man so etwas?

Da die tFrame-Klasse später mehr können muss, als sich selbst löschen, habe ich ein fOnDeleteJob-NotifyEvent eingebaut. Im MainForm (tMainForm.DoDeleteJob) bearbeite ich dann den DELETE-Button-Click.

das ist meine abgeleitete tFrame-Klasse:

Code: Alles auswählen

TFrameJobDetail = class(TFrame)
    btnDelete: TButton;
    cbSubDir: TCheckBox;
    lblJobID: TLabel;
    lblPath: TLabel;
    lblTimeStamp: TLabel;
    memoDesc: TMemo;
    pnl: TPanel;
    procedure btnDeleteClick(Sender: TObject);
    procedure FrameResize(Sender: TObject);
  private
    fJobID         : integer;
    fOnDeleteJob   : tNotifyEvent;
 
    procedure DoSetJobID(newJobID: integer);
  public
    constructor Create(TheOwner: TComponent); override;
    destructor Destroy; override;
  published
    property JobID: integer read fJobID write DoSetJobID;
    property OnDeleteJob: tNotifyEvent read fOnDeleteJob write fOnDeleteJob;
  end;


das wird beim DELETE-Button ausgeführt:

Code: Alles auswählen

procedure TFrameJobDetail.btnDeleteClick(Sender: TObject);
begin
  if assigned(fOnDeleteJob) then
    fOnDeleteJob(self);
end;

durch eine Action - ausgelöst durch einen Button auf dem Hauptformular - erzeuge ich neue tFrames:

Code: Alles auswählen

procedure tMainForm.actCreateJobExecute(Sender: TObject);
var
  newJobFrame : tFrameJobDetail;
 
begin
  newJobFrame := tFrameJobDetail.Create(sbJobs);
  newJobFrame.Name := 'JobDetail_' + IntToStr(sbJobs.ControlCount);
  newJobFrame.Parent := sbJobs;
  newJobFrame.JobID:=sbJobs.ControlCount;
  newJobFrame.Align := alTop;                                  // muss gesetzt sein, sonst gibt's keinen Scrollbalken
  newJobFrame.OnDeleteJob := @DoDeleteJob;
end;

Code: Alles auswählen

procedure tMainForm.DoDeleteJob(Sender: tObject);
var
  JobFrame    : tFrameJobDetail;
 
begin
  if not(Sender is tFrameJobDetail) then exit;
  JobFrame := Sender as tFrameJobDetail;
  JobFrame.Free;
end;

Ich wäre froh, wenn mir jemand einen Tipp geben könnte. Vielen Dank,
Gruss Frank
Zuletzt geändert von frawi am Mo 27. Dez 2010, 18:39, insgesamt 1-mal geändert.

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

Re: Selbsteliminierung führt zu SIGSEGV

Beitrag von theo »

http://wiki.lazarus.freepascal.org/Asynchronous_Calls" onclick="window.open(this.href);return false;

frawi
Beiträge: 3
Registriert: Mo 27. Dez 2010, 10:56

Re: Selbsteliminierung führt zu SIGSEGV

Beitrag von frawi »

Hallo theo,

vielen Dank für die rasche Antwort mit dem Link.

Ist der Ansatz über "asynchronous_calls" DIE Lösung? Ich möchte damit weder deine Antwort, noch die asynchronous_calls in Frage stellen.
Ich denke dabei eher, dass mein Design/Ansatz (sich selbst oder seine Parents zu löschen) schlecht ist. Sollte ich meine tFrames anderst löschen?

Ist es denn state-of-the-art in die Message-Queue einzugreifen?

Gruss Frank

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Selbsteliminierung führt zu SIGSEGV

Beitrag von Socke »

frawi hat geschrieben:Ist der Ansatz über "asynchronous_calls" DIE Lösung? Ich möchte damit weder deine Antwort, noch die asynchronous_calls in Frage stellen.
Ich denke dabei eher, dass mein Design/Ansatz (sich selbst oder seine Parents zu löschen) schlecht ist. Sollte ich meine tFrames anderst löschen?

Ist es denn state-of-the-art in die Message-Queue einzugreifen?
Manchmal weiß eine Komponente selbst am besten, wann es Zeit ist, die Bühne zu verlassen. Und das geht nur geordnet von Statten, wenn du entweder das ganze Programm beendet wird oder jemand anderes diese Komponente frei gibt.
Damit du den ganzen Kram dazu nicht selbst schreiben musst, kannst du auch einfach Application.ReleaseComponent() verwenden.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

frawi
Beiträge: 3
Registriert: Mo 27. Dez 2010, 10:56

Re: Selbsteliminierung führt zu SIGSEGV

Beitrag von frawi »

ich danke euch beiden für die prompte Hilfe. Ich habe es mit Application.ReleaseComponent() gelöst.

Code: Alles auswählen

procedure tMainForm.DoDeleteJob(Sender: tObject);
var
  JobFrame    : tFrameJobDetail;
 
begin
  if not(Sender is tFrameJobDetail) then exit;
  JobFrame := (Sender as tFrameJobDetail);
//  JobFrame.Free;                                           // führt zu SIGSEGV
  Application.ReleaseComponent(JobFrame);
end;

Antworten