Se7*_*7en 1 delphi vcl delphi-xe2
[编译:Delphi XE2]
昨天我花了一整天的时间尝试各种方法来完成这个特定的任务,但他们都以相同的结果结束了.
使用TRZCheckGroup和此示例查看已检查的内容等.
procedure TFrmMain.cbOptionsChange(Sender: TObject; Index: Integer; NewState: TCheckBoxState);
var
ItmIndex0, ItmIndex1: Integer;
begin
{ Initialize ItemIndex's }
ItmIndex0 := -1;
ItmIndex1 := -1;
{ Return the position Index of the string's(0 and 1) }
ItmIndex0 := cbOptions.Items.IndexOf('One');
ItmIndex1 := cbOptions.Items.IndexOf('Two');
{ Which CheckBox has been Checked }
cbOptions.ItemChecked[ItmIndex0] := True;
cbOptions.ItemChecked[ItmIndex1] := False;
end;
Run Code Online (Sandbox Code Playgroud)
注意:^这不是我的最终代码只是我如何处理CheckBoxes的一个例子.
像 -
if cbOptions.ItemChecked[ItmIndex0] then
cbOptions.ItemChecked[ItmIndex1] := False
else cbOptions.ItemChecked[ItmIndex1] := True;
Run Code Online (Sandbox Code Playgroud)
他们第一次工作然后它总是评估为真,我理解为什么.当我取消检查第一个CheckBox时,else位才会生效,这显然不是我想要的结果.
似乎事件停止工作,并且由于某种原因,我的一些尝试已经解雇了两次.
关于cbListOptionsChange的NewState Param,这是什么,它能帮助我吗?
任何有关这方面的帮助将非常感激.
谢谢.
if cbOptions.ItemChecked[ItmIndex0] then
cbOptions.ItemChecked[ItmIndex1] := False
else if cbOptions.ItemChecked[ItmIndex1] then
cbOptions.ItemChecked[ItmIndex0] := False;
Run Code Online (Sandbox Code Playgroud)
如果第二个CheckBox被选中,那么看到这样的东西,然后我检查第一个它按需要工作,但显然之后你不能再检查第二个CheckBox.
Ken White - 片段(工作).将组件的名称替换为Default,因为人们可能会感到困惑,有时会帮助默认命名以保存将来的问题.
procedure TForm1.RzCheckGroup1Change(Sender: TObject; Index: Integer; NewState: TCheckBoxState);
var
i: Integer;
begin
// Keep this event from being fired again while we're here.
// Your code isn't clear about what the actual name of the
// component or this event, (the event is named `cbListOptionsChange`,
// but your code references `cbOptions` - I don't know which is
// correct, so change it if needed in the next line and
// the one in the `finally` block below. I'm using `cbListOptions`
// here.
RzCheckGroup1.OnChange := nil;
try
// If we're getting notified of a new item being checked...
if NewState = cbChecked then
begin
// Iterate through the items, unchecking all that aren't
// at the index that just became checked.
// I wouldn't use `for..in`, because the ordering works better here
for i := 0 to RzCheckGroup1.Items.Count - 1 do
if i <> Index then
RzCheckGroup1.ItemChecked[i] := False; // Ryan - Just changed to this from this cbListOptions.Items[i].Checked := False;
end;
// Ryan - Uncomment these two lines if you want one of them to be Checked at all times, this will set the CheckBox you are trying to Uncheck to Checked.
//if not RzCheckGroup1.ItemChecked[Index] then
// RzCheckGroup1.ItemChecked[Index] := True;
finally
// Reconnect the event
RzCheckGroup1.OnChange := RzCheckGroup1Change;
end;
end;
Run Code Online (Sandbox Code Playgroud)
我不熟悉TRZCheckGroup
,但您当前的代码将始终检查项目ItmIndex0
并取消选中另一项.
TCheckBoxState
在Delphi文档中定义为
TCheckBoxState = (
cbUnchecked,
cbChecked,
cbGrayed
);
Run Code Online (Sandbox Code Playgroud)
所以NewState
似乎告诉你新设置的状态CheckBox
,并Index
告诉你哪个复选框正在改变.大部分时间cbGrayed
都没有使用,因为它表示从未设置过的值; 它通常仅在您读取数据库中的BOOLEAN(或位)列时才有用,并且它为NULL.
这个事件并不意味着要交替出现两个复选框的状态,它会出现; 当一个项目(在一组项目中)改变它的状态时,它只是让你做出反应:
procedure TFrmMain.cbListOptionsChange(Sender: TObject; Index: Integer;
NewState: TCheckBoxState);
begin
case NewState of
cbUnchecked: // Do whatever when cbOptions.Items[Index] is unchecked
cbChecked: // Do whatever when cbOptions.Items[Index] is checked
cbGrayed: // Usually ignored unless NULL in db column is indicated
end;
end;
Run Code Online (Sandbox Code Playgroud)
要反转两个复选框的状态(将一个复选框更改为备用状态而另一个复选框相反),您可以使用类似的东西(使用两个标准TCheckBox
控件,并为它们的两个事件定义相同的OnClick
事件):
procedure TFrmMain.CheckBoxClick(Sender: Object);
var
ChkBox: TCheckBox;
BoxToToggle: TCheckBox;
begin
// If you're sure the event is only for TCheckBox
ChangingBox := TCheckBox(Sender);
// If there's a chance it's used for something else
// if (Sender is TCheckBox) then
// begin
// ChangingBox := TCheckBox(Sender);
//
// or
// ChangingBox := Sender as TCheckBox
if ChangingBox = CheckBox1 then
BoxToToggle := CheckBox2
else
BoxToToggle := CheckBox1;
// Disable this event for both checkboxes, so it doesn't
// fire recursively
ChangingBox.OnClick := nil;
BoxToToggle.OnClick := nil;
try
BoxToToggle.Checked := not ChangingBox.Checked;
finally
// Reconnect event handlers
ChangingBox.OnClick := CheckBoxClick;
BoxToToggle.OnClick := CheckBoxClick;
end;
Run Code Online (Sandbox Code Playgroud)
但是,如果您只是处理一个项目列表,其中应该检查一个项目而其他所有项目都未选中,那么您应该使用一个项目TRadioGroup
.它会自动为您提供此行为.使用复选框与正常的Windows GUI行为相反,会使用户感到困惑.
有了这样说(并且我强烈反对这样做!),并且未经测试,因为我没有你正在使用的组件,你可以试试这个(这样做反对我更好的判断甚至写!):
procedure TFrmMain.cbListOptionsChange(Sender: TObject; Index: Integer;
NewState: TCheckBoxState);
var
i: Integer;
begin
// Keep this event from being fired again while we're here.
// Your code isn't clear about what the actual name of the
// component or this event, (the event is named `cbListOptionsChange`,
// but your code references `cbOptions` - I don't know which is
// correct, so change it if needed in the next line and
// the one in the `finally` block below. I'm using `cbListOptions`
// here.
cbListOptions.OnChange := nil;
try
// If we're getting notified of a new item being checked...
if NewState = cbChecked then
begin
// Iterate through the items, unchecking all that aren't
// at the index that just became checked.
// I wouldn't use `for..in`, because the ordering works better here
for i := 0 to cbListOptions.Items.Count - 1 do
if i <> Index then
cbListOptions.Items[i].Checked := False;
end;
finally
// Reconnect the event
cbListOptions.OnChange := cbListOptionsChange;
end;
end;
Run Code Online (Sandbox Code Playgroud)
为了确保清楚,我认为这是一个非常糟糕的主意,如果你为我工作,我不会允许它.如果有一个合适的选项,IMO就做出与预期的Windows行为相反的事情是完全错误的.