Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Eindeutige Combobox-Auswahl sicherstellen


onfire - Di 11.09.12 09:43

Moderiert von user profile iconNarses: Abgetrennt von [url=http://www.entwickler-ecke.de/viewtopic.php?t=110162]hier[/url].

Lassen sich auch Ereignisse der combobox in einer Schleife verwirklichen. Bspw will ich bei jeder der 10 combobox wenn eine auswahl erfolgt vergleichen ob die auswahl nicht in einer anderen combobox schon drin steht.
Bisher hab ich das ganze sehr unelegant gelöst und jeder einzelnen combobox als ereignis onclick

Delphi-Quelltext
1:
2:
3:
4:
5:
For z:=1 to 18 do
Begin
If Tcombobox(findcomponent(‚combobox‘ + inttostr(z)).text = combobox1.text
Then showmessage (‘ungültig’)
Else if z=1 then

Zugewiesen.. mit 2 schleifen wäre es ja möglich jedes mit jedem zu vergleichen außer sich selbst.. allerdings bräucht ich hilfe bei der erstellung der 3. Schleife für das „on click ereignis“ der 10 combobox felder (zusatz die felder sollten auch unterschiedlich bestückt werden.. zbsp erst 10. Combobox dann 9. Dann 8.)
Dachte vllt es geht in die richtung wie

Delphi-Quelltext
1:
2:
For i:=1 to 18 do
Tcombobox(findcomponent(‚combobox‘ + inttostr(i)).onclick

Gruß

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


Narses - Di 11.09.12 10:34

Moin und :welcome: in der EE!

Etwas wirr, deine Beschreibung, ich habe mal Folgendes daraus entnommen: Du hast 10 zur Designtime angelegte Comboboxen (welcher Auswahlstil eigentlich? csDropDownList? Dann kannst du - wenn die Einträge alle gleich sind - auch über .ItemIndex gehen, dass spart die Stringvergleiche). Dann solltest du erstmal von der Nutzung von FindComponent in einer Schleife absehen, das ist keine so gute Idee. Statt dessen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
type
  TForm1 = class(TForm)
    ComboBox1: TComboBox;
    //...
  public
    CBA: array[0..9of TComboBox; // Combo-Box-Array

// beim Programmstart
procedure TForm1.FormCreate(Sender: TObject);
  var
    i: Integer;
begin
  for i := 0 to 9 do // die Referenzen ermitteln
    CBA[i] := TComboBox(FindComponent('ComboBox'+IntToStr(i+1)));

Wenn du allen Comboboxen dieses OnSelect-Ereignis zuweist, sollte eine nicht-eindeutige Auswahl (Vergleich erfolgt von "hinten" nach "vorne" :arrow: downto) gemeldet werden:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
// bei einer Änderung der Auswahl Eindeutigkeit sicherstellen
procedure TForm1.ComboBoxSelect(Sender: TObject);
  var
    i: Integer;
begin
  for i := 9 downto 0 do // die Controls von "hinten" nach "vorne" durchsuchen
    if (CBA[i] <> Sender) then // das gerade bearbeitete Control weglassen
      if (CBA[i].Text = TComboBox(Sender).Text) then begin // schonmal ausgewählt?
        ShowMessage('Ungültig!');
        Exit; // bei einem Treffer schon abbrechen
      end;

cu
Narses


onfire - Sa 15.09.12 12:49

ok.. hab ich verstande.. und funktioniert auch einwandfrei..

mein problem ist ja aber das ich ganz viele comboboxen hab.. 10 stück muss ich jetzt die prozedur jedesmal neu eingeben.. oder geht das auch als schleife also bisher lös ichs so...


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
 procedure TForm1.ComboBox1Select(Sender: TObject);
  var
    i: Integer;
begin
  for i := 9 downto 0 do // die Controls von "hinten" nach "vorne" durchsuchen
    if (CBA[i] <> Sender) then // das gerade bearbeitete Control weglassen
      if (CBA[i].Text = TComboBox(Sender).Text) then begin // schonmal ausgewählt?
        ShowMessage('Ungültig!');
        Exit; // bei einem Treffer schon abbrechen
      end;

procedure TForm1.ComboBox2Select(Sender: TObject);
...

procedure TForm1.ComboBox3Select(Sender: TObject);
...

procedure TForm1.ComboBox4Select(Sender: TObject);
...
[/quote]

außerdem möchte ich wenn der fall eintritt das die combobox felder gleich sind das dann wieder eine leere auswahl erfoglt habs mit
[delphi] combobox1.text:='';
versucht geht aber nicht
usw....


platzwart - Sa 15.09.12 13:47

Du kannst allen Comboboxen die gleiche Ereignisroutine "ComboBox1Select" zuweisen.


onfire - So 16.09.12 16:54

folgende Frage...
klappt alles wunderbar und ein dickes dankeschön bishierher :)
ich versuche jetzt auch Edit-Fleder miteinander zu vergleichen.. hab aber bisher ein problem..


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
 
 procedure TForm1.Edit1Exit(Sender: TObject);

 var BA: array[0..17of TEdit;
i: integer;
begin
  for i := 0 to 17 do // die Referenzen ermitteln
    begin
    BA[i] := TEdit(FindComponent('Edit'+IntToStr(i+1)));
    end;


begin
  for i := 17 downto 0 do // die Controls von "hinten" nach "vorne" durchsuchen
    if (BA[i] <> Sender) then // das gerade bearbeitete Control weglassen
      if (BA[i].Text = TEdit(Sender).Text) then
      begin // schonmal ausgewählt?
        ShowMessage('Ungültig!');[/quote]

        Exit; // bei einem Treffer schon abbrechen
      end
end;
end;


allerdings will ich die feldervergleichen erst bei einem button click ereignis anwenden... hab das ganze einem button click ereignis zugeordnet nur es mahct nicht was es tun soll


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
[quote]procedure TForm1.Button1Click(Sender: TObject);

 var BA: array[0..17of TEdit;
i: integer;
begin
  for i := 0 to 17 do // die Referenzen ermitteln
    begin
    BA[i] := TEdit(FindComponent('Edit'+IntToStr(i)));
    end;


begin
  for i := 17 downto 0 do // die Controls von "hinten" nach "vorne" durchsuchen
    if (BA[i] <> Sender) then // das gerade bearbeitete Control weglassen
      if (BA[i].Text = TEdit(Sender).Text) then
      begin // schonmal ausgewählt?
        ShowMessage('Ungültig!');
        Exit; // bei einem Treffer schon abbrechen

end;


end;
end;


Narses - So 16.09.12 22:19

Moin!

user profile icononfire hat folgendes geschrieben Zum zitierten Posting springen:
hab aber bisher ein problem..
Leider, du hast nicht verstanden, was der Code tut. :?

user profile icononfire hat folgendes geschrieben Zum zitierten Posting springen:
allerdings will ich die feldervergleichen erst bei einem button click ereignis anwenden... hab das ganze einem button click ereignis zugeordnet nur es mahct nicht was es tun soll
Was macht es denn und was sollte es machen? :nixweiss: Detailierte Fehleranalyse ist der erste Schritt zur Erkenntnis. :idea: ;)

@all: Ja, ich habe das "Problem" bereits gesehen, aber er soll es bitte selbst herausfinden und damit die Funktion des Codes verstehen. :mahn:

cu
Narses


onfire - Mo 17.09.12 13:35

Ok.. ich habs.. naja vllt :D
Der Fehler liegt bei dem verwendetet Sender.. beim onExit Ereignis übertrage ich noch ein Sender der in der Routine verwendet wird.. das Programm weis was es mit was vergleichen muss..
Dagegen beim buttonclick ist kein Sender vorhanden die Routine macht einfach gar nichts und vergleicht deshalb auch nichts.. ich brauch beim buttonclick einfach gar kein Sender statdessen vergleiche ich nur array mit array und lasse das array weg wo ich grad vergleich^^
Quasi so in der art.. (ohne delphi zur hand zu haben versuch ichs mal)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
 
var BA: array[0..17of string;
i: integer;
begin
  for i := 0 to 17 do // die Referenzen ermitteln
    begin
    BA[i] := TEdit(FindComponent('Edit'+IntToStr(i)));
    end;


begin
  for i := 17 downto 0 do // die Controls von "hinten" nach "vorne" durchen
for q := 17 downto 0 do 
    if (i <> q) then // das gerade bearbeitete Control weglassen
      if (BA[i] = BA[q]) then
      begin // schonmal ausgewählt?
        ShowMessage('Ungültig!');
        Exit; // bei einem Treffer schon abbrechen

end;
end;
end;


oder? :)


Narses - Mo 17.09.12 14:31

Moin!

user profile icononfire hat folgendes geschrieben Zum zitierten Posting springen:
oder? :)
Jup, so etwa sollte das klappen. ;)

Noch ein Tipp: Das Ermitteln der Referenzen machst du doch hoffentlich nicht immer wieder vor dem Vergleichen, oder? :hair: Das reicht einmal bei Programmstart. :idea:

Und noch was Generelles: Den Code vernünftig einzurücken ist nicht etwas für Sauna-unten-Sitzer :zwinker: sondern hilft ungemein beim Lesen (und Verstehen) der Funktion des Quelltextes! Du solltest das alleine schon für dich, geschweige denn für andere Leser, berücksichtigen. :zustimm:

cu
Narses


onfire - Mo 17.09.12 14:48

wie formatier ich den den code richtig.. hab da was in erinnerung das des mit ner tastenkombination super einfach geht..
nur der ist mir entfallen.. oder kann ich das auch über bearbeiten.. quelltext formatieren mit einem klick?


Narses - Mo 17.09.12 15:47

Moin!

user profile icononfire hat folgendes geschrieben Zum zitierten Posting springen:
wie formatier ich den den code richtig.. hab da was in erinnerung das des mit ner tastenkombination super einfach geht..
Es gibt da keine in Stein gemeißelten Regeln, aber du kannst ja mal nach Suche bei Google STYLEGUIDE DELPHI suchen, da sollte es schon was zu geben. :les:

user profile icononfire hat folgendes geschrieben Zum zitierten Posting springen:
oder kann ich das auch über bearbeiten.. quelltext formatieren mit einem klick?
Generell rate ich davon ab, einen Wizard oder sowas für eine automatische Formatierung zu verwenden, weil man dann nicht mehr darüber nachdenkt, auf welcher Ebene der Code denn eigentlich sein sollte. :nixweiss: Gerade als Anfänger sollte man das schön manuell machen (wobei man mit der TAB-Taste Zeilen und mit Strg+I/U auch Blöcke ein/ausrücken kann). :idea:

cu
Narses