Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Reihenfolge components


neuling321 - So 22.05.16 21:38
Titel: Reihenfolge components
Hallo

ich habe mir eine Prozedur gemacht, die meine
TEdit Felder auf Inhalt prüfen soll.

Das funktioniert auch, ich habe nur eine frage zu der Reihenfolge.
Die TEdit Felder werden mir, wenn Sie leer sind, nach einer Reihenfolge angezeigt die
ich nicht ganz nachvollziehen kann. Kann man auf die Reihenfolge Einfluss nehmen?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
procedure TForm1.CheckFelder;
var
  I : integer;
  NameOfObject : string;

begin
  for I := 0 to componentcount -1  do
  begin
    if (Components[I] is TEdit) then
    begin
      if (TEdit(form1.components[I]).Text) = '' then
      begin
        NameOfObject := Components[I].name;
        if (NameOfObject <> 'txtprogname'AND (NameOfObject <> 'txtprognr'then
        begin
          delete(NameOfObject,1,3);
          showmessage('Bitte Feld ' + AnsiUpperCase(NameOfObject) + ' ausfüllen');
        end;
      end;
    end;
  end;
end;



Moderiert von user profile iconNarses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Di 24.05.2016 um 13:31


mandras - Mo 23.05.16 01:07

Was meinst Du mit "wenn sie leer sind" (zur Entwurfs/Laufzeit?)

Die Reihenfolge ist unabhängig davon sein ob sie leer sind oder nicht.

Wird wirklich eine bestimmte Reihenfolge hinsichtlich .components gewünscht
müßte man das Formular per ALT-F12 bearbeiten, hat aber keine endgültige Sicherheit daß
die so gemachte Reihenfolge stets erhalten bleibt.

Also nochmals die Frage: Reihenfolge in welcher Hinsicht und vor allem: Wofür?


Delete - Mo 23.05.16 02:08

- Nachträglich durch die Entwickler-Ecke gelöscht -


Nersgatt - Mo 23.05.16 07:02

Ich würde das etwas anders lösen. Mach doch eine Liste mit Controls, die überprüft werden sollen.

Deklariere z.B. eine TList<TEdit> als private Variable des Formulars. Im FormCreate erstellst Du die Variable und fügst alle Felder, die überprüft werden sollen der Liste in der gewünschten Reihenfolge hinzu.

In Deinem FeldChecker benutzt Du dann nicht mehr form1.Components sondern Deine private Liste der zu überprüfenden Felder.
So kannst Du auch komfortabel ein Feld hinzufügen, ohne gezwungenermaßen zu prüfen. Vielleicht hast Du ja mal ein Feld, das auch leer bleiben darf.


jaenicke - Mo 23.05.16 08:54

Ich würde da auch gleich eine zweite Liste mit einer Bezeichnung füllen, damit nicht nur der Name der Komponente angezeigt werden kann.

user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Ich vermute mal, er meint in welcher Reihenfolge ein Control den Fokus beim Tabulieren erhält.
Nein, er meint die Reihenfolge, in der die Controls auf Leerheit :) geprüft und dementsprechend dem Bediener gemeldet werden. Das kann der TabOrder entsprechen, muss aber nicht.


JoelH - Mo 23.05.16 12:42

Ich benutz für sowas immer die Tag Eigenschaft der Komponenten.


neuling321 - Di 24.05.16 20:49

Hallo

Danke für die Antworten.

Ja so wie jaenicke das gesagt hat so meine ich das. Durch den TapOrder lässt sich das nicht steuern.
Wie meint ihr das mit der Liste?


Nersgatt - Di 24.05.16 21:55

user profile iconneuling321 hat folgendes geschrieben Zum zitierten Posting springen:
Wie meint ihr das mit der Liste?

Welche Delphiversion benutzt Du? Davon hängt ab, wie man den Vorschlag mit der Liste am besten umsetzt.
Trag die Version am besten in Deinem Profil ein.


neuling321 - Di 24.05.16 22:25

Delphi 10 Seattle


jaenicke - Di 24.05.16 23:57

Dann kannst du ja Generics verwenden. Ein Beispiel:

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:
25:
26:
27:
28:
29:
30:
type
  TMainForm = class(TForm)
  ...
  private
    FNonEmptyEdits: TList<TEdit>;
    FNonEmptyEditDescriptions: TList<string>;
  end;

// OnCreate des Formulars
  FNonEmptyEdits := TList<TEdit>.Create;
  FNonEmptyEditDescriptions := TList<string>.Create;

  FNonEmptyEdits.Add(edtExample1);
  FNonEmptyEditDescriptions.Add('Beispiel-Edit 1');
  FNonEmptyEdits.Add(edtExample2);
  FNonEmptyEditDescriptions.Add('Beispiel-Edit 2');

// OnDestroy des Formulars
  FNonEmptyEdits.Free;
  FNonEmptyEditDescriptions.Free;

// Prüfung
procedure TMainForm.CheckFelder;
var
  i: integer;
begin
  for i := 0 to FNonEmptyEdits.Count - 1 do
    if FNonEmptyEdits[i].Text = '' then
      ShowMessage('Bitte Feld ' + FNonEmptyEditDescriptions[i] + ' ausfüllen');
end;
Du führst also eine Liste mit den zu prüfenden TEdit-Komponenten (hier edtExample1 und edtExample2) und eine zweite Liste mit den anzuzeigenden Feldnamen. So kannst du immer eine Liste von TEdit-Komponenten in der gewünschten Reihenfolge prüfen und zusätzlich einen richtigen Text dazu anzeigen statt nur den Komponentennamen, der ja relativ limitiert ist (keine Leerzeichen, ...).


Nersgatt - Mi 25.05.16 14:18

Genau so hab ich das gemeint. :zustimm:
Im obersten USES-Abschnitt muss noch Generics.Collections hinzugefügt werden.


neuling321 - So 29.05.16 07:33

Vielen Dank klappt super :-)


neuling321 - So 29.05.16 07:48

Nun habe ich doch noch ein Problem, ich habe in dem Programm noch
Memo und Comboboxen, die ich auch abfragen möchte.
Nun wird es aber kompliziert mit der abfrage, da die Felder alle
gemischt sind. Kann man den Objekten nicht irgendwie einen Index zuweisen?


jaenicke - So 29.05.16 10:03

Dann fällt mir eine andere Möglichkeit ein... ich bin grad am Handy, ich schreibe nachher etwas dazu.


jaenicke - So 29.05.16 12:00

Es gibt viele Möglichkeiten. Eine davon ist eine Prüfklasse zu schreiben, die von einer gemeinsamen Basisklasse abgeleitet ist. Dadurch wird die Information zu der entsprechenden Komponente beim Aufruf nicht mehr benötigt.

Beispiel:

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:
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:
type
  TCustomCheckText = class
  private
    FText: string;
  public
    constructor Create(const AText: string);
    function Check: Boolean; virtualabstract;
    property Text: string read FText;
  end;

  TCheckEditText = class(TCustomCheckText)
  private
    FEdit: TCustomEdit;
  public
    constructor Create(const AEdit: TCustomEdit; const AText: string);
    function Check: Boolean; override;
  end;

  TCheckComboText = class(TCustomCheckText)
  private
    FComboBox: TComboBox;
  public
    constructor Create(const AComboBox: TComboBox; const AText: string);
    function Check: Boolean; override;
  end;

implementation

{ TCheckEditText }

function TCheckEditText.Check: Boolean;
begin
  Result := FEdit.Text <> '';
end;

constructor TCheckEditText.Create(const AEdit: TCustomEdit; const AText: string);
begin
  inherited Create(AText);
  FEdit := AEdit;
end;

{ TCheckComboText }

function TCheckComboText.Check: Boolean;
begin
  Result := FComboBox.Text <> '';
end;

constructor TCheckComboText.Create(const AComboBox: TComboBox; const AText: string);
begin
  inherited Create(AText);
  FComboBox := AComboBox;
end;

{ TCustomCheckText }

constructor TCustomCheckText.Create(const AText: string);
begin
  FText := AText;
end;

Und die Benutzung:

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:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
  private
    FNonEmptyChecks: TList<TCustomCheckText>;
    procedure CheckFelder;

// ...

procedure TMainForm.CheckFelder;
var
  i: integer;
  MessageText: string;
begin
  MessageText := '';
  for i := 0 to FNonEmptyChecks.Count - 1 do
    if not FNonEmptyChecks[i].Check then
      MessageText := MessageText + #13#10 + 'Bitte Feld ' + FNonEmptyChecks[i].Text + ' ausfüllen';
  ShowMessage(MessageText);
end;

procedure TMainForm.btnStartClick(Sender: TObject);
begin
  CheckFelder;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  FNonEmptyChecks := TList<TCustomCheckText>.Create;

  FNonEmptyChecks.Add(TCheckEditText.Create(edtExample1, 'Beispiel-Edit Nummer 1'));
  FNonEmptyChecks.Add(TCheckEditText.Create(memExample, 'Beispiel-Memo'));
  FNonEmptyChecks.Add(TCheckComboText.Create(cboExample, 'Beispiel-Combobox'));
  FNonEmptyChecks.Add(TCheckEditText.Create(edtExample2, 'Beispiel-Edit Nummer 2'));
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  FNonEmptyChecks.Free;
end;


neuling321 - So 29.05.16 16:10

Wow, das muss ich mir erst mal in Ruhe zu Gemüte führen :shock: :shock:
So gut bin ich in Delphi noch nicht :oops: :oops: