Mehrere Checkboxen voneinander abhängig machen
Es gibt durchaus CheckBox-Gruppierungen, wo diese sich, in Kombination, gegenseitig ausschließen. Dann wäre ein Verhalten, wie in einer RadioGroup doch ganz angenehm für den Anwender. Dieses 'RadioGroup-Verhalten' lässt sich beispielsweise so realisieren:
Einfache Lösung (bis zu 3 CheckBoxen):
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72:
| unit Unit1;
interface
uses
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) GroupBox1: TGroupBox; CheckBox1: TCheckBox; CheckBox2: TCheckBox; CheckBox3: TCheckBox; CheckBox4: TCheckBox; CheckBox5: TCheckBox; procedure FormCreate(Sender: TObject); private procedure CheckBoxXYZStatus(BoxNr: Integer); procedure CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure CheckBoxXYZKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); public end;
var Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject); var i: integer; begin for i := 0 to GroupBox1.ControlCount-1 do with TCheckBox(GroupBox1.Controls[i]) do begin Tag := i; OnMouseUp := CheckBoxXYZMouseDown; OnKeyUp := CheckBoxXYZKeyDown; end; TCheckBox(GroupBox1.Controls[0]).State := cbchecked;end;
procedure TForm1.CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin CheckBoxXYZStatus((Sender as TCheckBox).Tag); end;
procedure TForm1.CheckBoxXYZKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = ORD(#32) then CheckBoxXYZStatus((Sender as TCheckBox).Tag); end; procedure TForm1.CheckBoxXYZStatus(BoxNr: Integer); var i: Integer; begin for i := 0 to GroupBox1.ControlCount-1 do if i <> BoxNr then TCheckBox(GroupBox1.Controls[i]).State := cbUnchecked; end;
end. |
Bei mehr als 3 CheckBoxen wird es zu umfangreich; also bietet sich u.a. folgende Lösung an:
Beispiel 2
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;
type TForm1 = class(TForm) GroupBox1: TGroupBox; procedure FormCreate(Sender: TObject); private aCheckBox: array[1..5] of TCheckBox; procedure CheckBoxXYZStatus(BoxNr: Integer); procedure CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure CheckBoxXYZKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); public end;
var Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject); var i: integer; begin for i := Low(aCheckBox) to High(aCheckBox) do begin aCheckBox[i] := TCheckBox.Create(Self); with aCheckBox[i] do begin Parent := GroupBox1; Top := 10 + i * 30; Left := 10; Tag := i; Caption := 'CheckBoxG'+IntToStr(i+10); OnMouseUp := CheckBoxXYZMouseDown; OnKeyUp := CheckBoxXYZKeyDown; end; end; aCheckBox[1].Caption := '...'; end;
procedure TForm1.CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin CheckBoxXYZStatus((Sender as TCheckBox).Tag); end;
procedure TForm1.CheckBoxXYZKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = ORD(#32) then CheckBoxXYZStatus((Sender as TCheckBox).Tag); end;
procedure TForm1.CheckBoxXYZStatus(BoxNr: Integer); var i: Integer; begin for i := Low(aCheckBox) to High(aCheckBox) do if i <> BoxNr then aCheckBox[i].State := cbUnchecked; end; end. |
Beispiel 3 Die Checkboxen sind zur Entwicklungszeit in eine GroupBox eingefügt:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) GroupBox1: TGroupBox; CheckBox1: TCheckBox; CheckBox2: TCheckBox; CheckBox3: TCheckBox; CheckBox4: TCheckBox; CheckBox5: TCheckBox; procedure FormCreate(Sender: TObject); private procedure CheckBoxXYZStatus(BoxNr: Integer); procedure CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure CheckBoxXYZKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); public end;
var Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject); var i: integer; begin for i := 0 to GroupBox1.ControlCount-1 do with TCheckBox(GroupBox1.Controls[i]) do begin Tag := i; OnMouseUp := CheckBoxXYZMouseDown; OnKeyUp := CheckBoxXYZKeyDown; end; TCheckBox(GroupBox1.Controls[0]).State := cbchecked;end;
procedure TForm1.CheckBoxXYZMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin CheckBoxXYZStatus((Sender as TCheckBox).Tag); end;
procedure TForm1.CheckBoxXYZKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = ORD(#32) then CheckBoxXYZStatus((Sender as TCheckBox).Tag); end; procedure TForm1.CheckBoxXYZStatus(BoxNr: Integer); var i: Integer; begin for i := 0 to GroupBox1.ControlCount-1 do if i <> BoxNr then TCheckBox(GroupBox1.Controls[i]).State := cbUnchecked; end;
end. |
Der 'Trick' bei allen Lösungen ist der, dass das OnMouseUp-Ereignis und das OnKeyUp-Ereignis zusammen mit der Methode CheckboxXYZ.State zur Statusänderung benutzt wird. In beiden Ereignissen wird die Prozedur
CheckboxXYZStatus zur entsprechenden Statusänderung aufgerufen.
Bei den Beispielen 2 und 3 wird die Eigenschaft
.Tag genutzt, um diese als Parameter an die Prozedur
CheckBoxXYZStatus zu übergeben.
Bei der 2.Lösung werden die Checkboxen zur Laufzeit in einem Array erstellt, während im Beispiel 3 die CheckBoxen zur Designzeit in eine GroupBox eingefügt sind und bei der TGroupBox die Eigenschaft Controls genutzt wird (Anregung von
Lannes).
Beachte: Jede Statusänderung einer Checkbox löst das Ereignis OnClick() aus
Werden Statusänderungen anderer Checkboxen in diesem Ereignis angestossen, kann das zu unerwünschten Symptomen bzw sich gegenseitigen Aufschaukeln führen.
OnMouseUp() bzw OnKeyUp() sind deshalb die geeigneten Ereignisse, weil der Status der Checkbox zu diesem Zeitpunkt schon eindeutig ist, d.h. der Status ist gesetzt.
Danke an
Narses,
Lannes,
jasocul für Anregungen/Kritik etc...
Moderiert von Th69: Fehler im 3. Code-Beispiel behoben (CheckboxStatus -> CheckboxXYZStatus).
Moderiert von Th69: Kleinere Rechtschreibfehler korrigiert.