Czyli mam liczby 1,5,7,8,10,13 i teraz zmieniam 8 powiedzmy na 9 - chciałbym aby ciąg po zmianie wyglądał w ten sposób: 1,5,7,9,10,13 mają Panowie jakieś sugestie?
Z tego wychodzi, że jeśli jest już zaznaczonych dokładnie sześć liczb, to przy zaznaczeniu siódmej program ma znaleźć najbliższą, która jest mniejsza od nowo zaznaczonej i ją odznaczyć. Nic trudnego. Problem nie polega na odznaczaniu nadmiarowej liczby, a na organizacji komponentów i ustawieniu ich w taki sposób, aby kodu nie trzeba było pisać dużo.
Sugeruję abyś sobie zadeklarował listę obiektów (przycisków) i np. w konstruktorze okna wpisał referencje wszystkich tych przycisków do tej listy. Dzięki temu komponenty wyszuka się raz, a później będzie można bazować wyłącznie na tej dodatkowej liście. Zdarzenie OnChange
wygeneruj tylko dla pierwszego przycisku i przypisz je wszystkich pozostałym. Odstawiam, że używasz przycisków klasy TToggleBox
, więc to zdarzenie będzie odpowiednie.
Czyli po kolei. Najpierw zadeklaruj pomocniczą listę dla referencji tych przycisków i kilka metody służace do jej utworzenia, wypełnienia i zwolnienia. W Delphi powinno to wyglądąć tak:
type
TMainForm = class(TForm)
{..}
private
FNumberBoxes: TList<TToggleBox>;
private
procedure InitNumberBoxes();
procedure FillNumberBoxes(AParent: TWinControl);
procedure DoneNumberBoxes();
{..}
end;
{..}
procedure TMainForm.InitNumberBoxes();
begin
FNumberBoxes := TList<TToggleBox>.Create();
end;
procedure TMainForm.FillNumberBoxes(AParent: TWinControl);
var
InnerControl: TControl;
ControlIndex: Integer;
begin
for ControlIndex := 0 to AParent.ControlCount - 1 do
begin
InnerControl := AParent.Controls[ControlIndex];
if InnerControl is TToggleBox then
FNumberBoxes.Add(InnerControl as TToggleBox);
end;
end;
procedure TMainForm.DoneNumberBoxes();
begin
FNumberBoxes.Free();
end;
Teraz w konstruktorze i destruktorze wywołaj te metody:
procedure TMainForm.FormCreate(Sender: TObject);
begin
InitNumberBoxes();
FillNumberBoxes(NumberBoxesPanel);
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
DoneNumberBoxes();
end;
Ten NumberBoxesPanel
to nazwa panelu, w którym osadzone są przyciski z numerkami (i tylko one). Aby wiedzieć ile przycisków jest zaznaczonych w danym momencie, przyda się dodatkowe pole:
type
TMainForm = class(TForm)
{..}
private
FNumberBoxesChecked: Integer;
{..}
end;
Teraz należy wygenerować zdarzenie OnChange
pierwszego przycisku i przypisać to zdarzenie do wszystkich przycisków – dzięki temu będzie można w jednym miejscu reagować na kliknięcie dowolnego. No i w tym zdarzeniu odpowiednio reagujemy:
procedure TMainForm.ToggleBox1Change(Sender: TObject);
var
Box: TToggleBox absolute Sender;
BoxIndex: Integer;
begin
if Box.Checked then
Inc(FNumberBoxesChecked)
else
Dec(FNumberBoxesChecked);
if FNumberBoxesChecked > 6 then
for BoxIndex := FNumberBoxes.IndexOf(Box) - 1 downto 0 do
if FNumberBoxes[BoxIndex].Checked then
begin
FNumberBoxes[BoxIndex].Checked := False;
Break;
end;
end;
Najpierw sprawdzamy czy kliknięty przycisk został zaznaczony czy odznaczony i na tej podstawie inkrementujemy lub dekrementujemy licznik. Następnie sprawdzamy czy wciśniętych przycisków jest więcej niż 6
i jeśli tak, szukamy w pętli najbliższego wciśniętego przycisku, od indeksu tego klikniętego w kierunku początku listy. Po znalezieniu odznaczamy ten przycisk i kończymy pętlę.
Ważne jest to, aby lista zawierała referencje w kolejności rosnącej. I to wszystko.
Jeśli ktoś chce się pobawić to do załączników dodaję testowy projekt. Ale że Delphi nie używam, to projekt ten przeznaczony jest dla Lazarusa. W każdym razie działa prawidłowo.