![]() |
Hä? Warum ist das Ändern von Checked ein Click?
Ich will statt mit drei RadioButtons eine Auswahl mit zwei CheckBoxen lösen. Gedacht ist das so: beide Checkboxen können abgewählt sein, dann kann einer von beiden ausgewählt sein. Wird einer einer von den beiden ausgewählt, muss natürlich der andere abgewählt werden. Theoretisch sollte das damit möglich sein:
Delphi-Quellcode:
Jetzt passiert aber etwas was ich nicht verstehe. Klicke ich auf CheckBox1, um es auszuwählen, wird in der Prozedur CheckBox2.Checked auf False gestellt. Das führt aber dazu, dass die Prozedur CheckBox2Click aufgerufen wird, und CheckBox1.Checked auf False stellt. Warum das denn?
procedure TForm1.CheckBox1Click(Sender: TObject);
begin CheckBox2.Checked := False; end; procedure TForm1.CheckBox2Click(Sender: TObject); begin CheckBox1.Checked := False; end; Warum führt der Checked Code dazu, dass es als Click wahrgenommen wird? Führe ich den Code durch eine Button Prozedur, passiert das nicht. |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Weil jemand vor über 20 Jahren dachte es wäre cool so.
Und nun bleibt es so, weil is halt so. :angle: Einige haben sich über eine Ableitung, oder einen ClassHelper, da was gebaut. :zwinker:
Delphi-Quellcode:
OnChange ist für DevExpress (beim Delphi reicht OnClick)
//property CheckedNoClick: Boolean read GetCheckedNoClick write SetCheckedNoClick stored False;
procedure TMyCheckBox.SetCheckedNoClick(Value: Boolean); var _Click, _Change: TNotifyEvent; begin _Click := OnClick; _Change := Properties.OnChange; try OnClick := nil; Properties.OnChange := nil; Checked := Value; finally OnClick := _Click; Properties.OnChange := _Change; end; end; [EDIT] Ich wusste doch da gab's nochwas, aber sah es vorhin natürlich nicht. ![]() PS: ![]() |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Das ist nun mal das Standardverhalten.
Lösung 1 (quick-and-dirty): Du setzt das (allerdings protected) Property ClicksDisabled temporär auf True. Lösung 2 (sauber aber aufwändig): Du verwendest zwei Actions, die einen gemeinsamen Status manipulieren bzw. überwachen. |
AW: Hä? Warum ist das Ändern von Checked ein Click?
So isses. Und das ist gemäß Doku sogar so gewollt
Zitat:
Sherlock |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Das OnClick einer Checkbox wird immer ausgelöst, wenn sich der Checked-Staus ändert, sei es durch Anklicken oder aus dem Programm heraus. Sollte vielleicht besser OnChecked heißen.
Ich mache es immer so. Ohne Actions oder ClassHelper oder Ableitungen
Delphi-Quellcode:
DoCheckBox1Click und DoCheckBox2Click natürlich irgenwo vorher sinnvoll auf true setzen.
procedure TForm1.CheckBox1Click(Sender: TObject);
begin if not DoCheckBox1Click then exit; DoCheckBox2Click:=false; CheckBox2.Checked := False; DoCheckBox2Click:=true; end; procedure TForm1.CheckBox2Click(Sender: TObject); begin if not DoCheckBox2Click then exit; DoCheckBox1Click:=false; CheckBox1.Checked := False; DoCheckBox1Click:=true; end; |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Noch ein Q&D:
Du müsstest im Click-Event den Sender prüfen können. Kommt der von der falschen CheckBox führst du den Code nicht aus. Falls es mit dem Sender nicht geht, müsste das ActiveControl vermutlich auch als Test möglich sein. Nächste Möglichkeit: Wenn die CheckBox1 geklickt wird, den Eventzeiger von CheckBox2 auf nil setzen, dann die CheckBox2 umsetzen. Anschließend wieder das Event zuweisen. Das aktuelle Verhalten hat Vor- und Nachteile. Ich würde daher nicht grundsätzlich behaupten, dass es falsch ist. |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Genau dafür gibt es ja eben das ClicksDisabled. Das wird auch von den Actions so verwendet, wie dieser Code aus TButtonControl.ActionChange zeigt:
Delphi-Quellcode:
// prevent generating Action.OnExecute when the control gets checked
OldClicksDisabled := ClicksDisabled; ClicksDisabled := True; Self.Checked := Checked; ClicksDisabled := OldClicksDisabled; |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Zitat:
|
AW: Hä? Warum ist das Ändern von Checked ein Click?
Es fing ja schon damit an, dass auch die nutzerseitige Änderung im OnClick ankommt, und es kein OnChange gab/gibt. (DevExpress hat bei seiner TcxCheckBox zusätzlich ein OnChange)
und da das "Click" somit eigenlich "Change" bedeutet, ist es "richtig", dass es beim Change auch klickt :angle2: |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Hallo Delphi-PRAXiS,
vielleicht etwas OldSchool, aber das sollte auch noch funktionieren.
Delphi-Quellcode:
Besonders bei älteren Delphi-Versionen.var DontChange: Boolean = False; procedure TForm1.CheckBox1Click(Sender: TObject); begin if DontChange = True then Exit; DontChange := True; try CheckBox2.Checked := False; finally DontChange := False; end; end; procedure TForm1.CheckBox2Click(Sender: TObject); begin if DontChange = True then Exit; DontChange := True; try CheckBox1.Checked := False; finally DontChange := False; end; end; Liebe Grüße Klaus Schaaff |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Zitat:
|
AW: Hä? Warum ist das Ändern von Checked ein Click?
Delphi-Quellcode:
gehört sowieso in garkeine Delphiversion rein.
if ... = True then
|
AW: Hä? Warum ist das Ändern von Checked ein Click?
Hallo,
@Uwe Rabe: Zitat:
@himitsu Zitat:
Liebe Grüße Klaus Schaaff |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Minimierte Beispiele, sind eben nicht immer naturgeträu.
z.B. BOOL aus WinAPIs ist 32 Bit / 4 Byte groß und wird dann auf das 1 Byte (Boolean) umgebrochen, was aber eben im Delphi auch nicht ganz genau dem ByteBool entspricht. Unter Windows ist die Konstante "True" z.B. -1, aber im Pascal bzw. Delphi ist es +1. Boolean ist nunmal eben nicht 1 Bit, was wirklich ausschließlich 0 und 1 kennen würde. Außerdem kann ein Boolean eben aus anderen Werten gekastet generiert sein in C-Sprachen und z.B. Javascript geht auch ein
Delphi-Quellcode:
, wobei I = Integer ... alles <> 0 ist nunmal "True".
if (i)
Delphi-Quellcode:
var B: Boolean;
//B := Boolean(0); // immer False (aber geht auch nicht anders) B := Boolean(2); // eigentlich "True", aber eben nicht genau das "eine" True if B = True then ShowMessage('True') else if B = False then ShowMessage('False') else ShowMessage('auch True'); if B then ShowMessage('True') else if not B then ShowMessage('False') else ShowMessage('nie'); |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Zitat:
|
AW: Hä? Warum ist das Ändern von Checked ein Click?
Nja, bissl blöd lief wohl, dass es normal "unsichtbar" ist und es somit auch kaum jemand sah.
Gerade bei der CheckBox spräche ja nichts dagegen, dass endlich mal published zu machen. ![]() Uwe :stupid: |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Ich fände es auch gut, wenn es eine passende globale Einstellung gäbe. Allerdings könnte die natürlich auch zu Irritationen führen.
Zitat:
Zitat:
Sagst du denn dann auch im echten Leben: Wenn "das Wetter ist schön" wahr ist, gehe ich zum Fußballspielen. Wenn nicht, was macht es dann für einen Sinn, das im Quelltext so verklausuliert zu schreiben, unabhängig von den möglichen Fehlern? Beispiel getestet mit Delphi 1 (mit zusätzlich BoolToStr, das es dort noch nicht gibt) bis 7:
Delphi-Quellcode:
function Example(const AValue: string): Boolean;
begin Result := Boolean(CompareStr(AValue, 'Test')); end; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage('Echter Wert: ' + BoolToStr(Example('TestNix'), True) + sLineBreak + 'Manuelle Auswertung: ' + BoolToStr(Example('TestNix') = True, True)); end; |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Zitat:
Ein sichtbares, bzw. wirklich nutzbares Property an den CheckBoxen wäre schon nett. :-D Aber joar, vielleicht eine Einstellung in den IDE-Settings und Projekt-Settings, wo man das Default festlegen kann, für neue CheckBoxen. |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Hallo,
@Uwe Raabe @jaenicke ich habe StdCtrls.pas in allen Versionen von Delphi 5 bis Delphi 10 duchsuchen lassen nach 'ClicksDisabled' und 'FClicksDisabled'. Keine der Versionen von TCustomCheckBox enthält diese property. Eine Frage bleibt offen, die ich nicht exakt beantworten kann. Hatten Updates dieser Delphi Versionen vielleicht doch TCustomCheckBox property ClicksDisabled eingebunden? Ich finde es schade, dass es kein offizielles Tool gibt, um diese Fragen korrekt zu bentworten. Dagegen haben TButtonControl und TRadioButton ClicksDisabled. Ein Kuriosum gibt es dennoch:
Delphi-Quellcode:
Das ist die einzige Stelle.
procedure TCustomCheckBox.SetState(Value: TCheckBoxState);
begin if FState <> Value then begin FState := Value; if HandleAllocated then SendMessage(Handle, BM_SETCHECK, Integer(FState), 0); if not ClicksDisabled then Click; // <- Hier end; end; In Delphi wurden schon immer Quelltext-Dateien *.pas mit leicht verändertem Code ausgeliefert, als die complierten *.dcu. Das scheint ein solcher Fall zu sein. Alle Versuche mit Casts TButtonControl(CheckBox1).ClicksDisabled führten zu nichts, auch Debug dcu's dazu zuschalten brachten keinen Erfolg. Vielleicht hat jemand eine Idee, wie man doch zu CheckBox1.ClicksDisabled kommt. Liebe Grüße Klaus Schaaff |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Zitat:
Wie schon geschrieben, die TCheckBox funktioniert mit ClicksDisabled seit Delphi 4 so. |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Also wenn ich im Code versuche, bei einer TCheckBox eine Property oder Methode mit "click" zu finden bekomme ich nur "OnClick" , kein "ClicksDisabled"...
|
AW: Hä? Warum ist das Ändern von Checked ein Click?
Zitat:
Zitat:
Delphi-Quellcode:
type
TMyCheckBox = class(TCheckBox) end; ... TMyCheckBox(CheckBox1).ClicksDisabled := True; |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Zitat:
Delphi-Quellcode:
Eigenschaft in 'nem Nachfahren veröffentlichen?
...
TButtonControl = class(TWinControl) private FClicksDisabled: Boolean; ... protected ... property ClicksDisabled: Boolean read FClicksDisabled write FClicksDisabled; ... TCustomCheckBox = class(TButtonControl) ... TCheckBox = class(TCustomCheckBox) ...
Delphi-Quellcode:
type
TMyCheckBox = class(TCheckBox) published property ClicksDisabled: Boolean; end; |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Click ist nur Protected, also aus "deinem" Code auch nicht zugänglich.
Bei TButton dagegen wurde es nach Puplic verschoben, somit kann dort direkt aufgerufen werden. |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Delphi-Quellcode:
Ich glaube so ein Konstrukt hab ich in meinem Vierteljahrhundert Delphi erst einmal benutzt/benutzen müssen. Das ist mir einfach nicht mehr eingefallen...
type
TMyCheckBox = class(TCheckBox) end; ... TMyCheckBox(CheckBox1).ClicksDisabled := True; 3 x Danke! |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Viele nennen sowas
Delphi-Quellcode:
,
type THackedCheckBox = class(TCheckBox);
aber Einige haben sich angewöhnt es netter zu benennen
Delphi-Quellcode:
.
type TCheckBoxAccess = class(TCheckBox);
(das END ist optional, wenn ansonsten nichts verändert wird) Es ginge auch ohne es Umzubennen
Delphi-Quellcode:
type TCheckBox = class(StdCtrls.TCheckBox); // bzw. (Vcl.StdCtrls.TCheckBox)
Oberhalb das Form kann man damit auch lokal Komponenten "umbauen", welche so dann auch direkt auf der Form laden. (zur Laufzeit, nicht im FormDesigner) PS, siehe ![]() |
AW: Hä? Warum ist das Ändern von Checked ein Click?
Ja, es geht auch ohne anders genannten Typ. Das mache ich allerdings ungern, denn wenn man den Code dann kopiert, wundert man sich, dass er anderswo nicht funktioniert. Oder man postet ihn hier im Forum, ohne dran zu denken... :lol:
|
AW: Hä? Warum ist das Ändern von Checked ein Click?
Zitat:
|
AW: Hä? Warum ist das Ändern von Checked ein Click?
Liste der Anhänge anzeigen (Anzahl: 2)
Sehr gut ist auch TComboBox. Das hat die Ereignisse OnSelect und OnClick. Beide sind komplett identisch. So gibt es kein Ereignis fürs Klicken in die ComboBox, dafür aber eins fürs Drücken der Pfeiltasten: OnClick.
Ebenfalls gut: TListView.Items.Add verhält sich komplett anders, je nach dem Wert von Checkboxes. Ist Checkboxes False, passiert schlicht nichts. Ist Checkboxes True, werden gleich drei Ereignisse ausgelöst. Oder du klickst links auf das StateImage eines ListViews. Du erhältst einmal MouseDown und zweimal MouseUp, weil du das erste MouseUp bereits vorm Loslassen kriegst. Ich habe euch mal meine gesammelten Worst-Ofs der Delphi-Logik angehängt. |
AW: Hä? Warum ist das Ändern von Checked ein Click?
@Redeemer
Das abschließende #13#10 beim TStrings.Text ist eigentlich ein sLineBreak, bzw. ganz genau das ![]() Merkst du, wenn nicht für Windows kompiliert wird und die Unixoiden bloß ein #10 haben. Und dafür gibt es auch schon eine Lösung: ![]() [add] ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:23 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