Delphi-PRAXiS
Seite 1 von 2  1 2      

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 on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert (https://www.delphipraxis.net/175824-%5Bxyz%5D-methoden-nicht-aufrufen-wenn-programmcode-die-komponente-aendert.html)

Der schöne Günther 22. Jul 2013 11:03

on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert
 
Der Titel ist eine Katastrophe, bessere Vorschläge erbeten :oops:

Konkretes Beispiel: Setze ich in meiner VCL-
Delphi-Quellcode:
TRadioGroup
die Property
Delphi-Quellcode:
ItemIndex
um, so ergibt sich folgende Aufrufreihenfolge:

Code:
TCustomRadioGroup.SetItemIndex() -> TControl.Click -> myRadioGroup.OnClick()
Ich möchte nicht, dass das ganze Geraffel hintendran (onClick-Ereignishandler) ausgeführt wird, das ist doch nur dafür, wenn der Benutzer aktiv draufklickt und etwas ändern möchte.

Wie gehe ich hier am besten vor? Ist meine Absicht falsch? Setze ich das
Delphi-Quellcode:
onClick
-Ereignis vorher auf
Delphi-Quellcode:
nil
, ändere dann den
Delphi-Quellcode:
ItemIndex
und setze
Delphi-Quellcode:
onClick
wieder zurück?

Ich habe schon gesehen, wie Leute die Tag-Property dafür benutzt haben, um zwischen "eigener" Änderung und Veranlassung durch den Benutzer zu unterscheiden, aber das erscheint mir irgendwie nicht richtig...

Codehunter 22. Jul 2013 12:07

AW: on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert
 
Ich mache das meistens so, dass im jeweiligen Formular eine globale boolsche Variable existiert. Die wird abgefragt wenn ein OnClick oder sonstwas ausgeführt wird. Bei Operationen, die keine Eventhandler auslösen sollen, wird die Variable vorher gesetzt und am Ende der Operation wieder zurückgesetzt.

DeddyH 22. Jul 2013 12:11

AW: on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1222244)
Setze ich das
Delphi-Quellcode:
onClick
-Ereignis vorher auf
Delphi-Quellcode:
nil
, ändere dann den
Delphi-Quellcode:
ItemIndex
und setze
Delphi-Quellcode:
onClick
wieder zurück?

Das wäre IMO die einfachste Möglichkeit.

[edit] Oder evtl. ein BM_SETCHECK absetzen. Ähnliche Problematik, allerdings mit einer Checkbox: http://forum.delphi-treff.de/index.p...threadID=30618 [/edit]

jaenicke 22. Jul 2013 12:13

AW: on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert
 
Ich versuche alles so zu designen, dass der Fall gar nicht eintritt, d.h. so, dass die Eventhandler auch nur das machen, was eine Folge der Auswahl ist. Und diese direkte Folge benötige ich dann auch, wenn ich den Wert per Quelltext selbst setze.

Ansonsten benutze ich auch private Felder um das zu steuern, da man anders als bei Verwendung von Tag dafür auch am Variablennamen sieht was der tut. Wer Tag dafür benutzt gehört geteert und gefedert. ;-)

Das OnClick temporär zu entfernen halte ich auch nicht für sauber, da man dann in dem OnClick gar nichts davon merkt, dass es nicht immer greift und sich später vielleicht mal tot debuggt... das sollte schon auch dort unterschieden werden.

Der schöne Günther 22. Jul 2013 12:31

AW: on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert
 
Danke für die Antworten :thumb:

Zitat:

Zitat von jaenicke (Beitrag 1222258)
dass die Eventhandler auch nur das machen, was eine Folge der Auswahl ist. Und diese direkte Folge benötige ich dann auch, wenn ich den Wert per Quelltext selbst setze.

Ja, so sollte es eigentlich sein. Glaube ich.

Mein konkretes Beispiel:
  • Der Benutzer wählt etwas aus
  • Die
    Delphi-Quellcode:
    TRadioGroup
    zeigt eine Eigenschaft des ausgewählten Dings an
  • Der Benutzer kann es ändern indem er an der
    Delphi-Quellcode:
    TRadioGroup
    herumspielt

Ich könnte einen "Änderungen absenden"-Button (oder so ähnlich machen).

Oder damit leben, dass beim Setzen der TRadioGroup etwas so gesetzt wird, wie es schon ist.

Oder den onEvent-Handler kurzzeitig ausklinken.


Diese drei Möglichkeiten sehe ich :|

Uwe Raabe 22. Jul 2013 13:31

AW: on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert
 
Ich umgehen das Problem meistens mit einem Integer-Property, bei dem ich im Setter nur dann etwas mache, wenn es sich ändert.

Nehmen wir z.B. ein einfaches Form mit einer RadioGroup und einem Label. Die Pas-Datei sieht dann so aus:

Delphi-Quellcode:
type
  TForm238 = class(TForm)
    RadioGroup1: TRadioGroup;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure RadioGroup1Click(Sender: TObject);
  private
    FSelectedIndex: Integer;
    procedure SetSelectedIndex(const Value: Integer);
  public
    property SelectedIndex: Integer read FSelectedIndex write SetSelectedIndex;
  end;

...

procedure TForm238.FormCreate(Sender: TObject);
begin
  FSelectedIndex := RadioGroup1.ItemIndex;
end;

procedure TForm238.RadioGroup1Click(Sender: TObject);
begin
  SelectedIndex := RadioGroup1.ItemIndex;
end;

procedure TForm238.SetSelectedIndex(const Value: Integer);
begin
  if FSelectedIndex <> Value then
  begin
    FSelectedIndex := Value;
    Label1.Caption := RadioGroup1.Items[FSelectedIndex];
    RadioGroup1.ItemIndex := FSelectedIndex;
  end;
end;

Der schöne Günther 22. Jul 2013 14:06

AW: on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert
 
Das hatte ich natürlich zuallererst gemacht :-) - Erst schauen, ob ich es denn überhaupt erst ändern muss. Aber es bleibt ja immer noch der Fall dass
  1. Der Benutzer 'Ding 283' auswählt
  2. Die RadioGroup Auskunft über einen Zustand des Dings gibt
  3. Dieser Zustand ist anders als der des zuletzt ausgewählten Dings
  4. Ich durch die Änderung der RadioGroup Dinge auf das setzen möchte, was ich sowieso gerade ausgelesen habe

DeddyH 22. Jul 2013 14:30

AW: on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert
 
Gerade schnell ausprobiert:
Delphi-Quellcode:
procedure TFormTest.Button1Click(Sender: TObject);
var
  OldIndex: integer;
begin
  OldIndex := Radiogroup1.ItemIndex;
  if OldIndex >= 0 then
    SendMessage(Radiogroup1.Buttons[OldIndex].Handle, BM_SETCHECK, BST_UNCHECKED, 0);
  SendMessage(Radiogroup1.Buttons[1].Handle, BM_SETCHECK, BST_CHECKED, 0);
end;
Aaaaaber: das geht dann an der Logik der Radiogroup komplett vorbei, d.h. der ItemIndex wird nicht aktualisiert usw.

Uwe Raabe 22. Jul 2013 14:34

AW: on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1222276)
Das hatte ich natürlich zuallererst gemacht :-) - Erst schauen, ob ich es denn überhaupt erst ändern muss. Aber es bleibt ja immer noch der Fall dass
  1. Der Benutzer 'Ding 283' auswählt
  2. Die RadioGroup Auskunft über einen Zustand des Dings gibt
  3. Dieser Zustand ist anders als der des zuletzt ausgewählten Dings
  4. Ich durch die Änderung der RadioGroup Dinge auf das setzen möchte, was ich sowieso gerade ausgelesen habe

Ich kann dir nicht ganz folgen :?

Medium 22. Jul 2013 15:06

AW: on[XYZ]-Methoden: Nicht aufrufen wenn Programmcode die Komponente ändert
 
Ich halte das gesamte Thema für einen riesigen dicken Design-Fehler in der VCL. Solche Dinge müssen ein OnChange auslösen, aber um Himmels Willen doch kein OnClick! Wer sich auch immer was dabei gedacht hat. Die netten Endlosschleifchen, die man sich durch Ändern einer zunächst nicht unbedingt Klick-Relevanten Property in diversen Controls auf diese Weise einhandelt, stehen in keinem Verhältnis zu dem geringen Aufwand (eben ein Methodenaufruf mehr), wenn dann doch mit einer Änderung aus dem Programm heraus Dinge passieren sollen, die sonst nur beim echten Click stattfinden sollen. Über diesen Unfug ist bestimmt fast jeder angehende Delphianer nach spätestens 1 Jahr gestolpert.

Ich mache es bei Events, die gerade mal nicht feuern sollen bei dem was da kommt, halt wirklich dann einfach so, dass ich den Handler zwischen speicher, meinen Kram mache, und nachher wieder zurück. Mit ein wenig Resourcenschutzblöcken kann man zumindest auch dann noch verhindern, dass einem Exceptions ein Control ohne Event-Handler hinterlassen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:11 Uhr.
Seite 1 von 2  1 2      

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