2006. december 20., szerda

How to get unique ItemIndexes across multiple TRadioGroups


Problem/Question/Abstract:

Is there a clean, simple solution to this problem: You have three RadioGroups: RgA, RgB, and RgC. Each has the same three items (numbered 0, 1, and 2 - actual string values are irrelevant here). Initially, RgA.ItemIndex = 0, RgB.ItemIndex = 1, and RgC.ItemIndex =2. The problem is to ensure that each selection (ItemIndex) is unique across all the RadioGroups. If the user clicks RgA and changes its index to 2, RgC's ItemIndex must change to 0 (the unused value). You'll always have one RadioGroup with an ItemIndex of 0, one with 1, and one with 2.

Answer:

Here is a possible approach:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Menus, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    RadioGroup1: TRadioGroup;
    RadioGroup2: TRadioGroup;
    RadioGroup3: TRadioGroup;
    procedure FormCreate(Sender: TObject);
    procedure AllRadiogroupsClick(Sender: TObject);
  private
    { Private declarations }
    FRGroups: array[1..3] of TRadioGroup;
    FRGroupItemIndices: array[1..3] of 0..2;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  FRGroups[1] := RadioGroup1;
  FRGroups[2] := RadioGroup2;
  FRGroups[3] := RadioGroup3;
  for i := 1 to 3 do
  begin
    FRGroupItemIndices[i] := FRGroups[i].ItemIndex;
    FRGroups[i].Tag := i;
  end;
  { assumes indices have been set up correctly at design time! }
end;

procedure TForm1.AllRadiogroupsClick(Sender: TObject);
var
  oldvalue: Integer;
  swapWith: Integer;
  thisGroup: TRadioGroup;

  function FindOldValue(value: Integer): Integer;
  var
    i: integer;
  begin
    result := 0;
    for i := 1 to 3 do
      if FRGroupItemIndices[i] = value then
      begin
        result := i;
        break;
      end;
    if result = 0 then
      raise exception.create('Error in FindOldValue');
  end;

begin
  {Tag property of radiogroup stores index for arrays}
  {Find old value of the group that changed}
  thisGroup := Sender as TRadioGroup;
  oldvalue := FRGroupItemIndices[thisGroup.Tag];
  if oldvalue = thisGroup.ItemIndex then
    Exit;
  {Find the index of the group that currently has the value this group changed to}
  swapWith := FindOldValue(thisGroup.ItemIndex);
  {Change the array values}
  FRGroupItemIndices[thisGroup.Tag] := thisGroup.ItemIndex;
  FRGroupItemIndices[swapWith] := Oldvalue;
  {Change the Itemindex of the other group. Disconnect handler while doing so}
  with FRGroups[swapWith] do
  begin
    OnClick := nil;
    ItemIndex := oldValue;
    OnClick := AllRadioGroupsClick;
  end;
end;

end.

Nincsenek megjegyzések:

Megjegyzés küldése