Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi FMX: Seltsames Verhalten beim Entfernen von ListboxItems (https://www.delphipraxis.net/191356-fmx-seltsames-verhalten-beim-entfernen-von-listboxitems.html)

Sherlock 6. Jan 2017 09:39

FMX: Seltsames Verhalten beim Entfernen von ListboxItems
 
Hi,

ich hätte da gerne wieder mal ein Problem mit FMX unter Berlin 1.2. Man nehme:
  • Ein neues plattformübergreifendes Projekt
  • Auf das Formular kommen zwei TButtons und eine TListBox
  • Ein Button wird AddBtn genannt, der andere RemoveBtn
  • Dann ergänze man den Code wie im folgenden gezeigt
Delphi-Quellcode:
unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Layouts,
  FMX.ListBox, FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm1 = class(TForm)
    AddBtn: TButton;
    ListBox1: TListBox;
    RemoveBtn: TButton;
    procedure AddBtnClick(Sender: TObject);
    procedure DelBtnClick(Sender: TObject);
    procedure RemoveBtnClick(Sender: TObject);
  private
    {Private-Deklarationen}
  public
    {Public-Deklarationen}
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}


procedure TForm1.AddBtnClick(Sender: TObject);
var
  myListItem    : TListBoxItem;
  myDelBtn      : TSpeedButton;
begin
  myListItem := TListBoxItem.Create(ListBox1);
  myListItem.Parent := ListBox1;

  myDelBtn := TSpeedButton.Create(myListItem);
  myDelBtn.Parent := myListItem;
  myDelBtn.Width := 50;
  myDelBtn.Align := TAlignLayout.Right;
  myDelBtn.StyleLookup := 'trashtoolbuttonbordered';
  myDelBtn.OnClick := DelBtnClick;
end;

procedure TForm1.RemoveBtnClick(Sender: TObject);
begin
  if ListBox1.Count > 0 then
  begin
    ListBox1.ListItems[0].Free;
  end;
end;

procedure TForm1.DelBtnClick(Sender: TObject);
begin
  if TFmxObject(Sender).Parent is TListBoxItem then
  begin
    TListBoxItem(TFmxObject(Sender).Parent).IsSelected := True;
    ListBox1.Selected.Free;
    ListBox1.ItemIndex := -1;
  end;
end;

end.
Als Ergebnis kann man mit dem AddBtn Einträge in die Listbox hinzufügen, und mit dem RemoveBtn den jeweils obersten löschen. Das funktioniert wunderbar. In der Listbox gibt es aber netterweise noch einen weiteren Button pro Eintrag, mit dem gezielt dieser Eintrag entfernt werden kann. Wenn man das nutzt ist scheinbar auch alles in Butter, ABER die Titelleiste der Appilikation reagiert dann erst wieder auf Mausklicks, wenn man eine der Komponenten anklickt.:shock:
  1. Kann das jemand nachvollziehen?
  2. Weiss jemand wie man das korrigieren kann?

Sherlock

Rollo62 6. Jan 2017 12:43

AW: FMX: Seltsames Verhalten beim Entfernen von ListboxItems
 
Nicht getestet, aber ich würde auch die Events löschen.

Delphi-Quellcode:
procedure TForm1.RemoveBtnClick(Sender: TObject);
begin
  if ListBox1.Count > 0 then
  begin
    // So inder Art ...
    btn := ListBox1.ListItems[0].FindSpeedButton; // Müsste man in den Child-Compoents suchen ...
    btn.OnClick := nil;
    btn := nil;
    ListBox1.ListItems[0].Free;
  end;
end;
Damit nicht ein Event auf ein gelöschtes Control gefeuert wird.

Rollo

Sherlock 6. Jan 2017 14:49

AW: FMX: Seltsames Verhalten beim Entfernen von ListboxItems
 
Hmmm, ich verabschiede mich gerade in meiner eigentlichen Implementierung von der Löschen-Idee und möchte die Einträge einfach immer drin lassen (ist eine zur Laufzeit bestimmte fixe Anzahl).

Mich interessiert dennoch, ob das Verhalten ein Bug ist, oder mein Fehler. Im ersteren Fall würde ich einen Report machen, in letzterem wäre ich für Aufklärung dankbar.

Sherlock

Rollo62 6. Jan 2017 15:07

AW: FMX: Seltsames Verhalten beim Entfernen von ListboxItems
 
Kann ich mir nicht vorstellen.
Ich mache das zwar nicht so wie in deinem Beispiel, auch nicht mit TButtons, aber ich benutze andere, auch komplexere Komponenten wie TLayout, TImage, TRectangle, etc. als Child-Komponenten ohne Probleme.

Rollo

HolgerX 6. Jan 2017 17:01

AW: FMX: Seltsames Verhalten beim Entfernen von ListboxItems
 
Hmm..

Kenne zwar nur VCL, aber, Du machst IM BtnClick ein Free des Buttons selber, somit können events, welche NACH dem BtnCLick noch kommen könnten gegen einem nicht mehr vorhandenen Button laufen.

Unter VCL würde ich im BtnClick NUR ein PostMessage absetzen mit dem Index des Eintrages und dann in der Behandlungsroutine den ListBoxEntry löschen.
So ist sichergestellt, dass alle noch zum BtnClick gehöhrenden Events abgearbeitet sind, bevor der Btn selber gelöscht wird.

EWeiss 6. Jan 2017 17:13

AW: FMX: Seltsames Verhalten beim Entfernen von ListboxItems
 
gibt es kein BtnUp?
wäre wohl am ehesten dafür geeignet den btn auf NIL zu setzen.

gruss

Harry Stahl 6. Jan 2017 22:46

AW: FMX: Seltsames Verhalten beim Entfernen von ListboxItems
 
Zitat:

Zitat von HolgerX (Beitrag 1358281)
Hmm..

Kenne zwar nur VCL, aber, Du machst IM BtnClick ein Free des Buttons selber, somit können events, welche NACH dem BtnCLick noch kommen könnten gegen einem nicht mehr vorhandenen Button laufen.

Unter VCL würde ich im BtnClick NUR ein PostMessage absetzen mit dem Index des Eintrages und dann in der Behandlungsroutine den ListBoxEntry löschen.
So ist sichergestellt, dass alle noch zum BtnClick gehöhrenden Events abgearbeitet sind, bevor der Btn selber gelöscht wird.

Ja, genau das ist der Grund, das aufrufende Objekt wird zerstört, bevor das Event, das es ausgelöst hat, abgearbeitet wurde.

Die hier beschriebene Lösungs-Variante mit Postmessage ginge natürlich nur unter Windows. Es ginge aber das allgemeine Messaging (TmessageManager) oder man macht es z.B. so:

Delphi-Quellcode:
procedure TForm46.DelBtnClick(Sender: TObject);
var
  lbi: TListBoxItem;
begin
  if TFmxObject(Sender).Parent is TListBoxItem then
  begin
    lbi := TListBoxItem(TFmxObject(Sender).Parent);
    lbi.IsSelected := True;

    TTask.run (procedure
    begin
      TThread.Synchronize(NIL, procedure
        begin
          lbi.free;
          ListBox1.ItemIndex := -1;
      end);
    end);
  end;
end;
TTask.Run wird erst nach Beendigung des Klick-Events ausgeführt, dann kann man gefahrlos das Objekt zerstören.

Sherlock 9. Jan 2017 06:47

AW: FMX: Seltsames Verhalten beim Entfernen von ListboxItems
 
Ah, Klasse. Danke Harry. Hab zwar das Bedienkonzept geändert, aber als "Grundlagenwissen" ist das viel Wert. Danke an alle.

Sherlock


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:27 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