Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - "Nur Float TEdit" funktioniert nicht


Nano-Ware - So 08.05.11 11:17
Titel: "Nur Float TEdit" funktioniert nicht
Hey,

ich habe versucht, ein TEdit zu basteln, dass nur Kommazahlen akzeptiert. Er bombt mich mit Meldungen voll, dass die Typen inkompatibel sind und ich weiß leider nicht warum.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure Tfrm_monitor.ed_onlyfloat(Sender: TObject; var Key: Char);
begin

  if (Key in [',']) then
    Key := '.';

  if not ((Key in ['0'..'9''.']) or (Key = vk_delete) or (Key = VK_LEFT) or (Key = VK_RIGHT) or (Key = VK_RETURN)) then
    Key := #0;

end;


Danke schonmal


colaka - So 08.05.11 11:27

Hallo,

schreibe in das OnKeyPress-Ereignis den folgenden Code:


Delphi-Quelltext
1:
2:
if not (Key in [#8#13'0'..'9'',']) then   // #8 = BACKSPACE
  Key := #0;  // erlaubt nur die Eingabe von Zahlen, Komma, BACKSPACE und RETURN


Gruß Ebi


Hidden - So 08.05.11 12:34

Hallo,

Zu den inkompatiblen Typen: Wenn du Strg drückst und dein vk_xyz anklickst, wirst du sehen dass es einfach die Zahl ist. Zahlen kannst du aber mit Chars nicht so einfach vergleichen, weil Delphi typenstreng ist(und das hilft auch manchmal, weil es sonst vielleicht einfach "nicht funktioniert", wenn es sich um wirklich inkompatible Typen handelt, die nicht durch reine Umbenennung ineinander übergehen).

Deine erste Abfrage ist schon ganz nützlich, die würde ich drin behalten. Würde aber auf Key = ',' prüfen, statt auf Key in [','] :zwinker:

Einen zusätzlichen Fall habt ihr noch nicht bedacht: Es kann nur ein '.' pro Zahl geben.
Einfach und bedienerfreundlich wäre es, den alten Punkt rauszulöschen und den neuen an der passenden Stelle zu belassen: So kann man ihn einfach mal verschieben, statt dass einfach nichts passiert(das ist nämlich unintuitiv ;)).

À propos Intuition: Wenn du es ganz nett machen willst, machst du bei Fehleingabe ein Beep; und färbst das Editfeld kurz rot ein oder so :)

lg,


Tranx - So 08.05.11 12:43

Hallo,

problematisch ist auch, wenn Du zweimal '-', '+', ',' in deinem Text hast. Z.B.: '0,,4546' oder '+0+.00342'. Außerdem kommen '+' und '-' ja nur an der 1. Position vor.

Du solltest dann zusätzlich für ',' '-' '+' Abfragen einbauen:


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:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
  e: TEdit;
  p : integer;
begin
  e := Sender as TEdit;   // dann kannst Du beliebige Editfelder mit einer OnKeyPress-Prozedur bearbeiten, ohne die Prozedur an das Editfeld anzupassen.
                          // Beschränkung: Nut TEditkomponenten oder Nachfahren möglich!
  if not (Key in [#8#13#27'0'..'9'',''+''-']) then
    Key := #0;
  if Key in [',''+''-'then
  begin
    if (Pos(Key, e.Text) > 0then
      Key := #0;
  end;
  if Key in ['+''-'then
  begin
    p := e.SelStart+1;    // Position des Cursors speichern
    e.Text := Key + e.Text;
    Key := #0;
    e.SelStart := p;     // und wieder an Position zurückgehen
  end;
  if Key = #27 then
    e.Text := '';
  if Key = #13 then
    Label1.Caption := FormatFloat('0.#######', StrToFloat(e.Text));   // Hier übergibst Du das Ergebnis an eine Variable (nur ein Beispiel)
                                                                      // Alternativ kannst Du auch in der OnKeyDown-Prozedur das erledigen lassen. Dann aber 
                                                                      // #13 aus der ersten Abfrage herausnehmen oder in der OnKeyDown-Prozedur anschließend an die Übergabe
                                                                      // mit Key := 0; die Variable Key zurücksetzen. Dann wird OnKeyPress nicht mehr aufgerufen.
end;


Hidden - So 08.05.11 13:00

Vorschlag für Default-Verhalten: '-' bzw '+' überschreiben das Vorzeichen, egal wo sie gedrückt werden.


Tranx - So 08.05.11 13:21

Kein 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:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
  e: TEdit;
  c : char;
  s : string;
  p, p1 : integer;
begin
  e := Sender as TEdit;
  s := e.Text+#0;                 // wegen Umwandlung des ersten Zeichens in Char notwendig.
  if not (Key in [#8#13#27'0'..'9'',''+''-']) then
    Key := #0;
  if Key = ',' then    // Kommaposition wird auf aktuelle Pos. verschoben
  begin
    p := e.SelStart+1;
    p1 := Pos(Key, e.Text);
    if p1>0 then begin
      e.Text := Copy(e.Text,1,p1-1)+Copy(e.Text,p1+1,255);
      e.Text := Copy(e.Text,1,p-1) +','+Copy(e.Text,p+1,255);
      Key := #0;
      e.SelStart := p-1;
    end;
  end;
  if Key in ['+''-'then    // +, - werden gewechselt
  begin
    p := e.SelStart+1;
    c := s[1];    // Abfrage des ersten Zeichens   (Bei Leerstring im Editfeld ist s = #0, s.o.);
    if c in ['+','-'then
      e.Text := Copy(e.Text,2,255);
    e.Text := Key + e.Text;
    Key := #0;
    e.SelStart := p;
  end;
  if Key = #27 then
    e.Text := '';
  if Key = #13 then
    Label1.Caption := FormatFloat('0.#######', StrToFloat(e.Text));
end;



EDIT:

Das Ganze könnte auch als überladene (override) KeyPress-Prozedur in einem Nachfahre von TEdit nützlich sein. (Sozusagen ein TFloatEdit oder so). Das Ergebnis wäre dann eine Value-Eigenschaft, und statt Edit1.Text könnten man dann Edit1.Value abrufen. Aber sicher existiert schon irgendwo ein solcher Nachfahre von TEdit, oder?

Dann müsste allerdings jeder Bezug auf andere Objekte wie oben bei Key= #13 auf Label1, unterbleiben, weil diese ja zum Zeitpunkt der Erstellung der Komponente nicht bekannt sind. Das wird aber mehr als ersetzt durch die property (Eigenschaft) Value der neuen Komponente.