Delphi-PRAXiS
Seite 2 von 2     12   

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/)
-   -   verschränke ToggleBoxes (https://www.delphipraxis.net/183535-verschraenke-toggleboxes.html)

mkinzler 18. Jan 2015 10:39

AW: verschränke ToggleBoxes
 
Zitat:

Ich kenne keine Programmiersprache, bei der direkte Aufruf des Setters "sogar der einzige Weg" ist, um "auf private Felder zuzugreifen".
Von außen schon, in Sprachen ohne Properties wie z.B. Java.

Im Setter kann auch etwas mehr als "nur" die Zuweisung erfolgen, deshalb kann es auch intern sinnvoll sein den Setter aufzurufen.

Will ich sicherstellen, das weitere Contraints erfüllt werden, welche im Setter überprüft werden -> Aufruf Setter

Will ich den Wert auf jedenfall setzen -> direkter Zugriff auf Feld.

Sir Rufo 18. Jan 2015 10:47

AW: verschränke ToggleBoxes
 
Zitat:

Zitat von Dejan Vu (Beitrag 1286904)
Ich sehe gerade, das im Code die Methode 'SetStatus' als 'Setter' bezeichnet wird, was er ja gar nicht ist, denn wo keine Property, da auch kein Setter. Insofern führt das dann auch mal zu Misverständnissen. Richtig(er) sollte es also sein, eine private Property 'Status' einzuführen. Denn sonst sieht man ja nicht, das 'FStatus' und 'SetStatus' etwas miteinander zu zun haben.
Delphi-Quellcode:
Type
  TFoo = class
    property Status : boolean Read FStatus Write SetStatus;
  end;

Ah sehr schön, dass du meinen Text aufmerksam durchgelesen hast:
Zitat:

Zitat von Sir Rufo (Beitrag 1286872)
Erstelle dir eine Eigenschaft vom Typ
Delphi-Quellcode:
Boolean
mit einer Setter-Methode:

Soll ich es größer und bunter gestalten? Soll ich explizit noch dazu schreiben
Zitat:

Ich gehe mal davon aus, dass jeder weiß was eine Eigenschaft ist und wie man die erstellt, so dass diese eine Setter-Methode hat. Darum zeige ich hier jetzt nur die Setter-Methode. Die IDE erstellt zu einer Eigenschaft auch automatisch ein Feld, das gleichlautend wie die Eigenschaft ist, mit einem vorangestellten F.
Also eine Eigenschaft
Delphi-Quellcode:
property Status : Boolean;
bekommt durch die Code-Vervollständigung automatisch ein privates Feld
Delphi-Quellcode:
FStatus: Boolean;
und eine private Setter-Methode
Delphi-Quellcode:
procedure SetStatus( const Value : Boolean );

Sollte ich vorsichtshalber auch noch vermerken "Einatmen - Ausatmen! Und hübsch in dieser Reihenfolge und kontinuierlich!" :wall:

Jetzt mal wieder an die normaldenkende Allgemeinheit (jeder der sich dazu zählt, darf sich angesprochen fühlen)

Um aus diesen Toggle-buttons jetzt einen TriState zu machen, ändert man einfach das ViewModel ab (macht natürlich nur Sinn, wenn diese Information im Daten-Modell auch verwertet werden kann, logisch - aber genau das sind ja die Änderungen, die immer wieder auf einen zukommen) und schwups, ohne eine Änderung an der View, passiert alles wie gewünscht:
Delphi-Quellcode:
type
  TStatus = ( None, Prev, Next );

  TFooViewModel = class( TViewModelBase )
  private
    FStatus: TStatus;
    FButton2Checked: Boolean;
    FButton1Checked: Boolean;
    procedure SetStatus( const Value: TStatus );
    procedure SetButton1Checked( const Value: Boolean );
    procedure SetButton2Checked( const Value: Boolean );
    function GetButton1Checked: Boolean;
    function GetButton2Checked: Boolean;
  public

    property Button1Checked: Boolean read GetButton1Checked write SetButton1Checked;
    property Button2Checked: Boolean read GetButton2Checked write SetButton2Checked;
  end;

implementation

{ TFooViewModel }

function TFooViewModel.GetButton1Checked: Boolean;
begin
  Result := FStatus = TStatus.Prev;
end;

function TFooViewModel.GetButton2Checked: Boolean;
begin
  Result := FStatus = TStatus.Next;
end;

procedure TFooViewModel.SetButton1Checked( const Value: Boolean );
begin
  if GetButton1Checked <> Value
  then
    if Value
    then
      SetStatus( TStatus.Prev )
    else
      SetStatus( TStatus.None );
end;

procedure TFooViewModel.SetButton2Checked( const Value: Boolean );
begin
  if GetButton2Checked <> Value
  then
    if Value
    then
      SetStatus( TStatus.Next )
    else
      SetStatus( TStatus.None );
end;

procedure TFooViewModel.SetStatus( const Value: TStatus );
begin
  if FStatus <> Value
  then
    begin
      FStatus := Value;
      OnPropertyChanged( ['Button1Checked', 'Button2Checked'] );
    end;
end;

TForm1 18. Jan 2015 19:07

AW: verschränke ToggleBoxes
 
Zitat:

Zitat von Sir Rufo (Beitrag 1286901)
Dann packe die Logik doch einfach in diese Klasse oder schalte da einfach eine Klasse davor, die diese Logik innehat. Was man nicht macht, ist die Logik in der Form/View so an direkt mit den Controls zu verkoppeln, wie du das gemacht hast.

Nagut, überzeugt :wink:. Dennoch ist damit mein Problem nicht gelöst, denn es wird immer noch der OnChange aufgerufen, was ja eigentlich bei deinem Code kein Problem darstellen sollte, denn durch die Abfrage
Delphi-Quellcode:
if FStatus <> Value
, sollte bei dem ungewünschten Aufruf der folgende Code einfach übergangen werden. Dennoch tritt bei mir der Fall auf, wenn ich zurück wechseln möchte von FStatus:= false zu true, dass dann aus irgend einem Grund (ich habe keine Ahnung, aus Welchem) trotzdem in den if-Block gegangen wird und somit eine weitere Verkettung sozusagen "rekursiver" Aufrufe erfolgt. :gruebel: Hat jemand eine Idee, warum das passiert?

Im Prinzip könnte ich ja einfach komplett neue Methoden direkt als OnClick anlegen und den alten Code kopieren, aber mich interessiert es zu wissen, warum trotz der neuen Verknüpfung immer noch OnChange aufgerufen wird.

Sir Rufo 18. Jan 2015 19:55

AW: verschränke ToggleBoxes
 
Dann zeig doch mal deinen Code denn nur anhand deiner Beschreibung kann man da nichts finden

TForm1 18. Jan 2015 22:25

AW: verschränke ToggleBoxes
 
...Beim Schreiben viel mir gerade der Fehler auf, wo der Fehler lag...war ein einfacher Tippfehler :roll::wall: Der Code funktioniert jetzt prima:thumb:

Allerdings bleibt jetzt dennoch das Grundübel, nämlich, dass beim OnClick gleichzeitig das OnChange mit aufgerufen wird, obwohl ich das im Objektinspektor geändert habe. Das war eigentlich auch meine Ausgangsfrage. Weiß jemand über einen Bug in Lazarus bescheid, bei dem die Verknüpfungen der Events bei Löschen trotzdem bestehen bleiben?

Sir Rufo 18. Jan 2015 23:03

AW: verschränke ToggleBoxes
 
Ok, letzte Gelegenheit, dann frag einfach nicht mehr, bzw. ich bin solange raus bis:
Zitat:

Zitat von Sir Rufo (Beitrag 1286979)
Dann zeig doch mal deinen Code denn nur anhand deiner Beschreibung kann man da nichts finden


TForm1 19. Jan 2015 17:39

AW: verschränke ToggleBoxes
 
Oh.:shock: Dann habe ich mich wohl nicht verständlich ausgedrückt. Der Code funktioniert jetzt wunderbar, alles kein Problem. Ich kann ihn totzdem noch mal posten, auch wenn es nichts anderes ist, als bereits oben schon:
Delphi-Quellcode:
procedure TForm1.GehevorClick(Sender: TObject); //Diese Methoden sind beide OnClick, ich habe sie zuvor von OnChange auf OnClick geändert. Allerdings werden sie trotzdem immer noch als OnChange aufgerufen, wenn die Eigenschaft Checked der ToggleBox unten* neu zugewiesen wird.
begin
  SetRichtung(Gehevor.Checked);
end;

procedure TForm1.GehezurueckClick(Sender: TObject);
begin
 SetRichtung(not Gehezurueck.Checked);
end;

procedure TForm1.SetRichtung(const aValue: boolean);
begin
  if FRichtung <> aValue then
  begin
    FRichtung:= aValue;
    Gehevor.Checked:= FRichtung; //*Hier werden wieder die Methoden oben aufgerufen, obwohl diese als OnClick ja nicht aufgerufen werden sollten.
    Gehezurueck.Checked:= not FRichtung;
  end;
end;
Der Code funktioniert ohne Fehler und tut was er soll, da die if- Verzweigung davor schützt, dass eine "Endlosschleife" entsteht. Im Prinzip ist es also jetzt nur noch ein Schönheitsfehler, bzw, wie ich vermute Bug in Lazarus, den ich aber auch gerne verstehen würde. Ich habe also im Objektinspektor die Property OnChange geleert und OnClick befüllt und schließlich noch von Hand auf Gehevor/zurückClick umbenannt, dann dürfte die Methode doch nicht bei OnChange aufgerufen werden, oder?

Sir Rufo 19. Jan 2015 19:33

AW: verschränke ToggleBoxes
 
Aha, das ist aber ein völlig normales Verhalten und sollte auch so dokumentiert sein. Eine Änderung der Eigenschaft Checked löst auch einen OnClick-Event aus. Es kann auch genauso gut sein, dass beim Setzen der Eigenschaft Checked immer OnClick gefeuert wird und OnChange nur dann kommt, wenn Changed vorher anders war. Genauso gut kann es sogar (auch wenn es falsch wäre -> Bug) sein, dass beide Events immer gefeuert werden, wenn der Eigenschaft Checked ein Wert zugewiesen wird.

Das genaue Verhalten kann man sich im Quelltest der Komponente aber sehr schön anschauen, dann weiß man was da genau passiert.

TForm1 19. Jan 2015 21:25

AW: verschränke ToggleBoxes
 
Tatsächlich! OnClick wird auch dann ausgelöst, wenn Checked gesettet wird. Irgendwie bin ich davon ausgegangen, dass OnClick logischerweise nur dann ausgelöst wird, wenn man darauf klickt :wink:. Dann hat ja alles seine Richtigkeit, vielen Dank für die Info:thumb:

Und drauf gekommen, mal im Quellcode nachzuschauen bin ich natürlich auch nicht. :wall:


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:53 Uhr.
Seite 2 von 2     12   

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