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 TCheckBox.Checked löst OnClick aus? (https://www.delphipraxis.net/145519-tcheckbox-checked-loest-onclick-aus.html)

Leanahtan 3. Jan 2010 17:05


TCheckBox.Checked löst OnClick aus?
 
Ich habe gerade festgestellt, das eine Wertzuweisung an TCheckBox.Checked ein OnClick auslöst. Ist das normal? Wenn ja, kann man den Status auch ändern, ohne ein OnClick auszulösen? Hab mir jetzt erstmal notgedrungen mit OnMouseUp geholfen, aber mir leuchtet das Verhalten von Delphi an der Stelle nicht ganz ein. Bei was wird dann OnClick alles ausgelöst? :gruebel:

Jens Hartmann 3. Jan 2010 17:10

Re: TCheckBox.Enabled löst OnClick aus?
 
Hallo,

deine CheckBox hat ein OnClick Ereigniss. Das wird ausgelößt. Ist doch auch gut so, damit kannst Du ja schließlich was machen. Allerdings, wenn du nichts in dem Ereigniss hast, passiert auch nichts. Was steht den in deiner Zuweisung.

Gruß Jens

Matze 3. Jan 2010 17:18

Re: TCheckBox.Enabled löst OnClick aus?
 
Hallo,

bei einer Änderung von "Enabled" wird bei mir kein OnClick-Ereignis ausgelöst (Turbo Delphi).

Falls du dennoch wissen möchtest, wie man das OnClick-Ereignis vorübergehend deaktivieren kann, so ginge es:

Delphi-Quellcode:
CheckBox1.OnClick := nil;
CheckBox1.Enabled := not CheckBox1.Enabled;
CheckBox1.OnClick := CheckBox1Click;
Aber du solltest auf alle Fälle die Ursache finden, denn normal ist dein gezeigtes verhalten nicht.

Grüße, Matze

Jens Hartmann 3. Jan 2010 17:32

Re: TCheckBox.Enabled löst OnClick aus?
 
Zitat:

Zitat von Leanahtan
Hab mir jetzt erstmal notgedrungen mit OnMouseUp geholfen

Also, wenn ich das richtig verstanden habe, wird doch im normalen auf die Checkbox.Enebled := false, diese nur Enabled = false
und bei True umgekehrt. Jetzt ist aber doch die Frage, wie weißt Du den dieses Enabled zu.

Delphi-Quellcode:

Button.Click..
  begin
    Checkbox1.Enabled := false;
  end;
Gruß Jens

Leanahtan 3. Jan 2010 17:40

Re: TCheckBox.Enabled löst OnClick aus?
 
Danke für die Antworten. Erstmal hab ich mich verschrieben. :oops: Ich meinte natürlich checked und nicht enabled ^^

Also es gibt schon Fälle, wo man den Wert ändern will, ohne das ein OnClick ausgelöst wird. Ich habe z.B. eine Liste, und wenn ein Eintrag den Focus erhält, dann wird
Delphi-Quellcode:
WalkAbleCheckBox.Checked:=TGroundTile(GroundTilesListView.ItemFocused.Data).Walkable;
entsprechend dem zum Listeneintrag gehörigen Objekt geändert. Bei OnClick wird er hingegen ins Objekt geschrieben. Wäre im Prinzip kein Problem - aber ich nutze multiselect, um einzelne Werte für mehrere Objekte gleichzeitig zu ändern. Wenn mehrere Listeneinträge ausgewählt sind, dann wird bei OnClick der Wert für alle zugehörigen Objekte geändert. Das ist bei mir aber schon passiert, wenn der Nutzer nur einen weiteren Listeneintrag ausgewählt hat (weil dann ja WalkAbleCheckBox.Checked neu gesetzt wird).

Jens Hartmann 3. Jan 2010 17:51

Re: TCheckBox.Checked löst OnClick aus?
 
Hallo Leanahtan,

du hast recht. ich habe das gerade mal ausprobiert. Bei unten gezeigtem Code, kommt bei jedem Click auf den Button die MessageBox.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  CheckBox1.Checked := not CheckBox1.Checked
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  ShowMessage('OnClick wurde ausgeführt');
end;
Ändert man es ab, wie Matze geschrieben hat, ist der Fehler weg. Das ist ja keine Fehler, sondern scheinbar bei Delphi normal.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  CheckBox1.OnClick := nil;
  CheckBox1.Checked := not CheckBox1.Checked;
  CheckBox1.OnClick := CheckBox1Click;
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  ShowMessage('OnClick wurde ausgeführt');
end;
Gruß Jens

himitsu 3. Jan 2010 17:56

Re: TCheckBox.Checked löst OnClick aus?
 
einfache Möglichkeit:
In alle Ereignisprozeduren if FLocked then Exit; und wärend des Setzens von .Checked dieses FLocked (global in der Form) auf TRUE setzen.

andere Möglichkeit:
Bei der CheckBox und allen anderen CheckBoxen, mit dem gleichen GroupIndex, vor der Zuweisung auf .Checked das .OnClick auf NIL sezten
und nach dem Setzen die notfalls vorher gespeicherten Ereignisprozeduren wieder eintragen.

Leanahtan 3. Jan 2010 18:28

Re: TCheckBox.Checked löst OnClick aus?
 
Zitat:

Zitat von Jens Hartmann
Ändert man es ab, wie Matze geschrieben hat, ist der Fehler weg. Das ist ja keine Fehler, sondern scheinbar bei Delphi normal.

Schon möglich, dass das normal ist. Geht aber nicht unbedingt aus der Hilfe hervor (Zitat: Setzt den Wert der Eigenschaft Checked. ... SetChecked ist die als protected deklarierte Implementierung der Eigenschaft Checked. Durch Überschreiben der Methoden SetChecked und GetChecked ändern Sie die Eigenschaft Checked in abgleiteten Klassen. - zugegeben, bei OnClick steht es dann doch). Und es bleibt die Frage, warum dabei standardmäßig OnClick ausgelöst wird. Es muss doch eine "feste Regel" geben, damit man nicht immer ausprobieren muss, bei welcher Wertänderung eventuell auch noch irgendein Event ausgelöst wird.

Jens Hartmann 3. Jan 2010 18:32

Re: TCheckBox.Checked löst OnClick aus?
 
Zitat:

Zitat von Leanahtan
Es muss doch eine "feste Regel" geben, damit man nicht immer ausprobieren muss, bei welcher Wertänderung eventuell auch noch irgendein Event ausgelöst wird.

Aus Interesse: Da gebe ich Dir Recht. Ich habe das bislang auch nicht gewusst und suche gerade schon in meinem Programm, ob ich irgendwelche dieser Funktionen etc. eingebaut habe, wo mir das noch nicht aufgefallen ist.

Vieleicht kann das ja mal jemand näher erläutern.

Gruß Jens

Sharky 3. Jan 2010 18:45

Re: TCheckBox.Checked löst OnClick aus?
 
Ich glaube die CheckBoxen sind die einzigen mit diesem "Fehler". Besser wäre es gewesen das Ereigniss OnChange zu nennen. Dann wüsste jeder wann es ausgelöst wird.

Matze 3. Jan 2010 18:46

Re: TCheckBox.Checked löst OnClick aus?
 
Mich würde auch etwas interessieren: Der Parameter "Sender", wofür steht der genau? In der Delphi-Reference wurde ich nicht fündig.
Ich hätte erwartet, dass so etwas geht, doch ich habe "Sender" hier wohl falsch interpretiert:

Delphi-Quellcode:
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  if (Sender as TCheckBox) = CheckBox1 then
    // durch CheckBox1 ausgelöst
  else
    // durch andere Komponenten ausgelöst, bsp. einen Button
end;
Dann ist "Sender" wohl generell die Komponente, die das Ereignis direkt oder indirekt auslöst und somit hier immer CheckBox1, richtig?
Nur wenn diese Prozedur auch anderen CheckBox-Komponenten zugewiesen ist, kann der Parameter variieren und dann ist Sender die CheckBox, die das Ereignis ausgelöst hast.

Grüße, Matze

Progman 3. Jan 2010 18:49

Re: TCheckBox.Checked löst OnClick aus?
 
Es ist in der Tat so. Auch der folgende Code löst einen Beep aus:
Delphi-Quellcode:
procedure TForm2.Button1Click(Sender: TObject);
begin
  if CheckBox1.State = cbChecked then CheckBox1.State := cbUnChecked
   else CheckBox1.State := cbChecked;
end;

procedure TForm2.CheckBox1Click(Sender: TObject);
begin
  Beep;
end;
Ich glaube, wenn man trotzdem das OnClick der CheckBox nutzen will, muss man das mit eine Hilfs-Status-Variablen regeln:
Delphi-Quellcode:
procedure TForm2.Button1Click(Sender: TObject);
begin
  if CheckBox1.State = cbChecked then begin
    CanClick := False; // Hilfsvariable
    CheckBox1.State := cbUnChecked;
  end else begin
    CanClick := False;
    CheckBox1.State := cbChecked;
  end;
end;

procedure TForm2.CheckBox1Click(Sender: TObject);
begin
  if CanClick then begin
    Beep;
  end else CanClick := True;
end;
Dann funktioniert es :)

Matze 3. Jan 2010 18:53

Re: TCheckBox.Checked löst OnClick aus?
 
Zitat:

Zitat von Progman
Ich glaube, wenn man trotzdem das OnClick der CheckBox nutzen will, muss man das mit eine Hilfs-Status-Variablen regeln

Oder meine vorgeschlagene Umsetzung aus Beitrag #3 verwenden. Sie ist vielleicht nicht so sauber, aber meiner Meinung nach etwas übersichtlicher.

Hawkeye219 3. Jan 2010 19:29

Re: TCheckBox.Checked löst OnClick aus?
 
Hallo,

das Problem kann man ebenfalls erschlagen, indem man die Checkbox mit einer Action verknüpft und das Umschalten über die Eigenschaft Delphi-Referenz durchsuchenTAction.Checked durchführt. In diesem Fall wird nämlich das Click-Ereignis der Checkbox nicht ausgelöst. Zusätzlich erhält man so die Möglichkeit, weitere abhängige Controls (z.B. einen Menüeintrag) auf einfache Weise mit dem Status der Checkbox zu synchronisieren. Schließlich vereinfacht das Ereignis Delphi-Referenz durchsuchenTAction.OnUpdate noch das (De)Aktivieren der beteiligten Controls.

Gruß Hawkeye

Blup 4. Jan 2010 09:47

Re: TCheckBox.Checked löst OnClick aus?
 
Hier noch eine "saubere" Variante den Status zu setzen, ohne das Event auszulösen:
Delphi-Quellcode:
procedure SetCheckBox(ACheckBox: TCheckBox; AValue: Boolean);
var
  Event: TNotifyEvent;
begin
  with ACheckBox do
  begin
    Event := OnClick;
    try
      OnClick := nil;
      Checked := AValue;
    finally
      OnClick := Event;
    end;
  end;
end;
Grundsätzlich mit Action zu arbeiten, ist aber eventuell der bessere Weg.

hoika 4. Jan 2010 09:57

Re: TCheckBox.Checked löst OnClick aus?
 
Hallo,

Zitat:

Es muss doch eine "feste Regel" geben, damit man nicht immer ausprobieren muss, bei welcher Wertänderung eventuell auch noch irgendein Event ausgelöst wird.
Die feste Regel heisst, dass geschriebener Quellcode
auch getestet wird ...
Daß es bei eventgetriebenem Code schwieriger ist, ist nat. klar.

Bei mir steht in OnClick-Methoden z.B. auch kein direkter Code,
sondern der Aufruf einer eigenen Prozedur.

Dann noch einen Breakpoint auf diese Prozedur
und es gibt (fast) keine Überrauschungen.


Heiko


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:13 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz