OnButtonClick und Action-Methode

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

OnButtonClick und Action-Methode

Beitrag von MacWomble »

Soeben ist mir etwas aufgefallen was Zweifel erweckt, dass dies schon immer so war:

Durch Umstrukturierung meines Programms hatte ich auf einem Button ein Action eingetragen. Gleichzeitig war aber noch versehentlich die (aus einer früheren Programmversion) OnButtonClick-Funktion eingetragen.
(Sowohl die unter Action als auch die unter OnButtonClick abgelegte Methode hatten den selben Inhalt.)
Beim Klicken des Buttons wurden nun beide Events ausgeführt.

1. War dies schon immer so? :shock:
2. Ist dies beabsichtigt? Wenn ja, welcher Aufruf wird priorisiert ausgeführt?
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: OnButtonClick und Action-Methode

Beitrag von Michl »

MacWomble hat geschrieben:1. War dies schon immer so?
Ja, zumindest habe ich das eben mal bei 1.2.0 getestet.

MacWomble hat geschrieben:2. Ist dies beabsichtigt? Wenn ja, welcher Aufruf wird priorisiert ausgeführt?
Ich würde das aktuelle Verhalten als richtig einschätzen, da wenn der User einen Button klickt, sollte gemäß der System Messages auch immer OnMouseDown, OnClick und OnMouseUp gefeuert werden (oder sollten diese dann bei einer TActionzuweisung auch nicht mehr gefeuert werden). Aber man könnte ja mal Delphi testen, wie es sich dort verhält.

Zuerst wird der Event Handler von OnClick ausgeführt, dann von Action.OnExecute. Wenn du mit Actions arbeitest, dann stell doch alles auf diese um.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: OnButtonClick und Action-Methode

Beitrag von wp_xyz »

Mein Verständnis ist, dass es sich mit dem auszuführenden Event-Handler genauso verhalten sollte wie mit den anderen Properties, die von Actions verändert werden: Wenn ich z.B. einen Button mit einer Action verbinde, wird seine Caption durch die Caption der Action ersetzt; wenn ich hinterher die Caption des Buttons verändere, gilt diese. Der Button hat Priorität gegenüber der Action.

Genauso ist es mit dem Eventhandler bei Delphi (siehe beigefügtes Programm): Bei einem Klick auf einen Button, dem eine Action zugewiesen ist, der aber eine eigene OnClick-Routine hat, wird die OnClick-Routine ausgeführt - auf keinen Fall werden beide ausgeführt, so wie es bei Lazarus der Fall ist.

Ich denke, hier liegt ein Fehler vor, der gemeldet werden sollte. Ich erinnere mich, dass mit den Eventhandlern bei Actions vor einiger Zeit etwas geändert worden ist - hoffentlich ist da nichts ver-schlimm-bessert worden. Andererseits hat Michl recht, dass beide Events auch schon mit Laz 1.2 aufgerufen werden.

Das beigefügte Programm kann sowohl mit Delphi als auch mit Lazarus verwendet werden.

[EDIT]
Ich habe mir jetzt die in TControl eingeführte Click-Methode angesehen:

Code: Alles auswählen

procedure TControl.Click;
 
  function OnClickIsActionExecute: boolean;
  begin
    Result:=false;
    if Action=nil then exit;
    if not Assigned(Action.OnExecute) then exit;
    if not Assigned(FOnClick) then exit;
    Result:=CompareMethods(TMethod(FOnClick),TMethod(Action.OnExecute));
  end;
 
var
  CallAction: Boolean;
begin
  //DebugLn(['TControl.Click ',DbgSName(Self)]);
  CallAction:=(not (csDesigning in ComponentState)) and (ActionLink <> nil);
 
  // first call our own OnClick if it differs from Action.OnExecute
  if Assigned(FOnClick)
  and ((not CallAction) or (not OnClickIsActionExecute)) then
    FOnClick(Self);
  // then trigger the Action
  if CallAction then
    ActionLink.Execute(Self);
end;

Ich finde, die Routine müsste nach "FOnClick" verlassen werden, also so:

Code: Alles auswählen

procedure TControl.Click;
 
  function OnClickIsActionExecute: boolean;
  begin
    Result:=false;
    if Action=nil then exit;
    if not Assigned(Action.OnExecute) then exit;
    if not Assigned(FOnClick) then exit;
    Result:=CompareMethods(TMethod(FOnClick),TMethod(Action.OnExecute));
  end;
 
var
  CallAction: Boolean;
begin
  //DebugLn(['TControl.Click ',DbgSName(Self)]);
  CallAction:=(not (csDesigning in ComponentState)) and (ActionLink <> nil);
 
  // first call our own OnClick if it differs from Action.OnExecute
  if Assigned(FOnClick)
  and ((not CallAction) or (not OnClickIsActionExecute)) then begin
    FOnClick(Self);
    exit;            // <--- NEU
  end;
  // then trigger the Action
  if CallAction then
    ActionLink.Execute(Self);
end;

Damit zeigt mein Beispiel-Programm dasselbe Verhalten wie bei Delphi. Ich weiß natürlich nicht, ob diese Änderung irgendwelche Seiteneffekte bei anderen Controls hat...
Dateianhänge
action_button.zip
(4.38 KiB) 74-mal heruntergeladen

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: OnButtonClick und Action-Methode

Beitrag von Michl »

Ich denke OnClickIsActionExecute sollte genau das verhindern, daß der Event Handler doppelt aufgerufen wird, wenn es sich um die selbe Methode handelt, ansonsten werden beide aufgerufen.

[Edit]:
Wenn Delphi ein anderes Verhalten an den Tag legt, können wir die Methode stark vereinfachen:

Code: Alles auswählen

procedure TControl.Click;
begin
  //DebugLn(['TControl.Click ',DbgSName(Self)]);
  if csDesigning in ComponentState then Exit;
 
  if Assigned(FOnClick) then
    FOnClick(Self)
  else
  if Assigned(ActionLink) then
    ActionLink.Execute(Self);
end;
Keine Ahnung, ob das Verhalten jetzt besser ist?

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: OnButtonClick und Action-Methode

Beitrag von wp_xyz »

Früher wurde der OnExcute-Handler der Action im OnClick-Handler des Controls eingetragen, so wie bei Delphi übrigens auch. OnClickIsActionExecute prüft daher, ob die beiden Handler identisch sind. Jetzt bleibt OnClick bei Verwendung einer Action leer, und der jetzige Code erscheint mir etwas überholt zu sein. Ich denke schon, dass dein Code funktionieren sollte, Ich meine sogar, dass er auch vorher schon funktioniert hätte. Auf der anderen Seite, warum schreibt jemand so umständlichen Code wie den heutigen ohne Not, wenn nicht doch etwas dahinter steckt, an das wir nicht denken?

Ich habe übrigens eben die Änderung mit dem "exit" hochgeladen, so dass ab jetzt im Trunk nur noch 1 Event aufgerufen werden sollte.

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: OnButtonClick und Action-Methode

Beitrag von MacWomble »

Mit dem Exit funktionieren die Buttons des RXSidepanel nicht mehr in jedem Fall!

Das ist also nicht die Lösung !
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: OnButtonClick und Action-Methode

Beitrag von wp_xyz »

Nur weiß ich nicht, was das RXSIdepanel ist.

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: OnButtonClick und Action-Methode

Beitrag von MacWomble »

Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: OnButtonClick und Action-Methode

Beitrag von wp_xyz »

Ich hab's mir installiert. Find ich nicht. In welcher Datei ist das enthalten?

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: OnButtonClick und Action-Methode

Beitrag von MacWomble »

Sorry, TRXViewsPanel - hatte den Namen statt die Klasse abgelesen :oops:

Der OnClick auf Items wird nicht mehr immer erkannt, wenn das exit verwendet wird.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: OnButtonClick und Action-Methode

Beitrag von wp_xyz »

Nach einigem Hin-und-her habe ich das "exit" wieder rückgängig gemacht. Die Komponente könnte man zwar einfach fixen, aber möglicherweise haben andere auch noch dieses Problem. Und so groß ist der Vorteil von dem Fix nun auch wieder nicht.

Antworten