AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Auf Änderungen in TEdit reagieren

Ein Thema von Swann · begonnen am 19. Nov 2014 · letzter Beitrag vom 19. Nov 2014
Antwort Antwort
Swann

Registriert seit: 19. Nov 2014
3 Beiträge
 
#1

Auf Änderungen in TEdit reagieren

  Alt 19. Nov 2014, 14:48
Delphi-Version: XE2
Hallo allerseits,

als relativer Anfänger in Delphi stehe ich momentan des Öfteren vor folgendem Problem: Ich habe ein Formular mit diversen TEdit-Feldern. Teilweise hängen die Inhalte dieser Felder voneinander ab, so dass ich zum Beispiel beim Ändern des Inhalts von Edit1 auch Edit2 füllen möchte und beim Ändern von Edit2 auch Edit3. Bisher versuche ich meist, dies über das OnExit-Event zu steuern. Allerdings funktioniert das nicht so ohne weiteres, da eine Eingabe in Edit1 dann zwar Edit1.OnExit aufruft und Edit2 korrekt gefüllt wird, allerdings nicht mehr Edit2.OnExit aufgerufen wird. Ich bräuchte also ein Event, das nicht nur auf Benutzereingaben reagiert, sondern auch dann, wenn das Editfeld "automatisch" gefüllt wird.

Eine naheliegende Möglichkeit wäre hier wohl OnChange. Dabei gefällt mir wiederum nicht, dass dieses Event für jedes eingegebene Zeichen erneut gerufen wird, was bei noch unfertigen Eingaben nicht unbedingt sinnvoll erscheint. Zum anderen wird auch hier Edit2.OnChange zwar gerufen, wenn ich im Edit1.OnChange
Code:
Edit2.Text = EinString
ausführe, nicht aber, wenn ich schreibe
Code:
Edit2.AsInteger = EineZahl
Da ich nur mit Zahlen operiere, möchte ich es nach Möglichkeit vermeiden, diese als String in das Editfeld einzufügen.

Gibt es für diese Fragestellung ein Standardevent, das ich nicht kenne? Oder was ist die beste Lösung in diesem Fall?

Vielen Dank für Hilfe und beste Grüße,
Swann
  Mit Zitat antworten Zitat
Benutzerbild von baumina
baumina

Registriert seit: 5. Mai 2008
Ort: Oberschwaben
1.275 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Auf Änderungen in TEdit reagieren

  Alt 19. Nov 2014, 14:59
Da du niemals wissen kannst, wann ein Benutzer mit seiner Eingabe fertig ist, kannst du nur dem Benutzer irgendetwas zur Verfügung stellen dass er sagen kann, dass er jetzt fertig ist. z.B. ein Button.

Wenn du beim OnExit bleibst, müsstest du nach dem automatischen Füllen des 2. Editfeldes dessen OnExit-Code aufrufen.
Hinter dir gehts abwärts und vor dir steil bergauf ! (Wolfgang Ambros)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.139 Beiträge
 
Delphi 12 Athens
 
#3

AW: Auf Änderungen in TEdit reagieren

  Alt 19. Nov 2014, 15:28
TEdit (XE2) hat ein AsInteger?
Glaub ich nicht.
Und seb´lbst wenn, dann wäre es falsch implementiert, wenn es bei Zuweisung/Änderung kein OnChange auslöst.


Zitat:
Gibt es für diese Fragestellung ein Standardevent, das ich nicht kenne? Oder was ist die beste Lösung in diesem Fall?
Beschreib doch mal, wann das Event auslössen soll,
dann findet sich bestimmt etwas.

Da du niemals wissen kannst, wann ein Benutzer mit seiner Eingabe fertig ist, ...
Jupp.

OnChange -> es wurde grade etwas geändert (ob Eingabe fertig, ist dabei egal)
Darum gibt es neben StrToInt z.B. auch TryStrToInt und StrToIntDef.

OnExit -> fermutlich fertig, da Benutzer das Edit verlässt.
PS: Beim Klick auf Menüs, das [X] und ToolButtons, welche keinen Eingabefokus bekommen, wird dort niemals OnExit ausgelöst, da das Edit den Fokus nicht verliert.

Man kann natürlich nach OnChange noch etwas warten und erst dann reagieren, aber wenn der Benutzer ein bissl länger braucht, weil er z.B. noch bissl überlegen muß, muß er auch da noch nicht fertig sein.
Die WebCam anzapfen hilft auch nicht, da der Benutzer auch mal kurz weggehen kann, weil er was nachgucken muß, bevor er weitertippt.
usw.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Swann

Registriert seit: 19. Nov 2014
3 Beiträge
 
#4

AW: Auf Änderungen in TEdit reagieren

  Alt 19. Nov 2014, 16:34
Hallo ihr zwei,

vielen Dank schonmal für die raschen Antworten!

Wenn du beim OnExit bleibst, müsstest du nach dem automatischen Füllen des 2. Editfeldes dessen OnExit-Code aufrufen.
Es ist klar, dass das so geht. Allerdings wird der Code dadurch relativ unübersichtlich, und man muss gut aufpassen, dass man auch die OnExit-Methoden für wirklich alle Felder, die sich ändern können, aufruft. Daher hatte ich auf eine Möglichkeit gehofft, das Feld selbst überwachen zu lassen, wann es neuen Inhalt bekommt.


TEdit (XE2) hat ein AsInteger?
Glaub ich nicht.
Und seb´lbst wenn, dann wäre es falsch implementiert, wenn es bei Zuweisung/Änderung kein OnChange auslöst.
Ok, du hast in beiden Punkten recht. Zum einen handelt es sich nicht um ein einfaches TEdit, wie ich fälschlicherweise behauptet habe, sondern um eine Ableitung von TCustomEdit (nicht von mir geschrieben). Zum anderen habe ich da wohl nicht richtig aufgepasst, denn bei neuerlichem Testen merke ich nun, dass OnChange tatsächlich ausgelöst wird... Entschuldige bitte, mein Fehler.

Um mal ein etwas konkreteres Beispiel zu bringen: Edit1 dient dazu, die Stückzahl einer zu kaufenden Ware aufzunehmen, Edit2 den Preis pro Stück, Edit3 die Gesamtkosten, Edit4 eventuelle Rabatte und Edit5 den Endpreis (=Gesamtkosten - Rabatt). Ich habe also direkte Abhängigkeiten
Edit1 -> Edit3,
Edit2 -> Edit3,
Edit3 -> Edit5,
Edit4 -> Edit5.

Gleichzeitig gibt es eine Liste bereits getätigter Käufe. Wenn man dort auf einen Eintrag klickt, sollen die entsprechende Stückzahl und der entsprechende Preis in Edit1 und Edit2 gefüllt werden und daraus automatisch der Inhalt von Edit3 berechnet werden. OnChange tut in diesem Fall eigentlich schon das richtige. Ich hätte eben gern ein Eierlegende-Wollmilchsau-Event, das sich bei solchen automatischen Füllungen wie OnChange verhält, aber andererseits bei Benutzereingaben die Rechnungen erst durchführt, wenn der Nutzer auf Enter drückt oder das Feld sonstwie aus dem Fokus nimmt.

Viele Grüße,
Swann
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#5

AW: Auf Änderungen in TEdit reagieren

  Alt 19. Nov 2014, 16:53
Es ist klar, dass das so geht. Allerdings wird der Code dadurch relativ unübersichtlich, und man muss gut aufpassen, dass man auch die OnExit-Methoden für wirklich alle Felder, die sich ändern können, aufruft. Daher hatte ich auf eine Möglichkeit gehofft, das Feld selbst überwachen zu lassen, wann es neuen Inhalt bekommt.
Das tun sie doch mit dem OnChange-Ereignis, das prompt reagiert, wenn es neuen Inhalt bekommt. Fertige Programme gibt es dagegen noch nicht als Komponenten. Das mußt du schon noch selber programmieren. Du kannst z.B. OnKeyUp auswerten und z.B. das Betätigen der Entertaste = Chr(13) als Eingabe-Ende werten, was ja den allermeisten PC-Anwendern nicht neu oder gar fremd sein dürfte. Beim Programmseitigen Ändern der Anzeige mußt du dann dieselbe Procedure aufrufen wie beim Betätigen der Enter-Taste.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.139 Beiträge
 
Delphi 12 Athens
 
#6

AW: Auf Änderungen in TEdit reagieren

  Alt 19. Nov 2014, 18:09
Edit3 und Edit5 sind doch hoffentlich ReadOnly? Ansonsten einfach an Edit1, Edit2 und Edit4 ein OnChange-Event, da drin natürlich inkl. Fehlerprüfung (bei unvollständig und so) nacheinander die Werte für Edit3 und Edit5 berechnen.

Bei ungültigen Werten am Besten die jeweiligen Edits leer machen.


Egal ob nun ein OnChange an Edit1+Edit2 und Nocheines an Edit3+Edit4,
oder nur ein gemeinsames Event an Edit1 bis Edit4,
OnChange ist einfach das Einfachste.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Swann

Registriert seit: 19. Nov 2014
3 Beiträge
 
#7

AW: Auf Änderungen in TEdit reagieren

  Alt 19. Nov 2014, 20:17
Hallo himitsu,

Readonly sind die Editfelder bei mir nicht nicht, da es eben Gründe geben kann, dass der richtige Wert von dem berechneten Wert abweicht und der Nutzer daher nachträglich Änderungen vornehmen möchte (das Beispiel, das ich gegeben habe, stellt den Sachverhalt auch nur vereinfacht dar). Die Berechnung liefert nur die Voreinstellung der Felder.

Ich werd es dann wohl wirklich mittels OnChange machen und damit leben müssen, dass sich auch schon während des Eintippens die Felder munter verändern.

Danke für die Hilfe!

Viele Grüße,
Swann
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: Auf Änderungen in TEdit reagieren

  Alt 19. Nov 2014, 21:00
Hier mal ein kleines simples Beispiel, wie man auf sowas reagieren kann und das auch sehr elegant (und vor allem auch testbar) löst. (fertige EXE im Anhang)

Die Logik kommt in eine eigene überschaubare Klasse
Delphi-Quellcode:
unit Rechner;

interface

type
  TRechner = class
  private
    FWert1: string;
    FWert2: string;
    FWert3: string;
    FWert4: string;
    FWert3Berechnen: Boolean;
    function GetErgebnis1: string;
    function GetErgebnis2: string;
    procedure SetWert1( const Value: string );
    procedure SetWert2( const Value: string );
    procedure SetWert3( const Value: string );
    procedure SetWert4( const Value: string );
    function GetWert3: string;
  public
    property Wert1: string read FWert1 write SetWert1;
    property Wert2: string read FWert2 write SetWert2;
    property Ergebnis1: string read GetErgebnis1;
    // Berechnet aus Wert1 und Wert2 oder freie Eingabe
    property Wert3: string read GetWert3 write SetWert3;
    property Wert3Berechnet: Boolean read FWert3Berechnen;
    property Wert4: string read FWert4 write SetWert4;
    property Ergebnis2: string read GetErgebnis2;
  end;

implementation

uses
  System.SysUtils;

{ TRechner }

function TRechner.GetErgebnis1: string;
var
  Val1, Val2: Integer;
begin
  if TryStrToInt( FWert1, Val1 ) and TryStrToInt( FWert2, Val2 )
  then
    Result := IntToStr( Val1 + Val2 )
  else
    Result := '';
end;

function TRechner.GetErgebnis2: string;
var
  Val1, Val2: Integer;
begin
  if TryStrToInt( FWert3, Val1 ) and TryStrToInt( FWert4, Val2 )
  then
    Result := IntToStr( Val1 + Val2 )
  else
    Result := '';
end;

function TRechner.GetWert3: string;
begin
  if FWert3Berechnen
  then
    begin
      FWert3 := GetErgebnis1;
    end;
  Result := FWert3;
end;

procedure TRechner.SetWert1( const Value: string );
begin
  if FWert1 <> Value
  then
    begin
      FWert1 := Value;
      FWert3Berechnen := True;
    end;
end;

procedure TRechner.SetWert2( const Value: string );
begin
  if FWert2 <> Value
  then
    begin
      FWert2 := Value;
      FWert3Berechnen := True;
    end;
end;

procedure TRechner.SetWert3( const Value: string );
begin
  if FWert3 <> Value
  then
    begin
      FWert3 := Value;
      FWert3Berechnen := False;
    end;
end;

procedure TRechner.SetWert4( const Value: string );
begin
  if FWert4 <> Value
  then
    begin
      FWert4 := Value;
    end;
end;

end.
Was hat die Form noch zu tun? Fast nix:
Delphi-Quellcode:
unit Form.Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,

  Rechner;

type
  TForm1 = class( TForm )
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    procedure FormShow( Sender: TObject );
  private
    FIsLoading: Boolean;
    FRechner: TRechner;
    procedure SaveToRechner;
    procedure LoadFromRechner;
    procedure SyncWithRechner;
  public
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
  published
    procedure ControlChange( Sender: TObject );
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
{ TForm1 }

procedure TForm1.AfterConstruction;
begin
  inherited;
  FRechner := TRechner.Create;
end;

procedure TForm1.BeforeDestruction;
begin
  inherited;
  FRechner.Free;
end;

procedure TForm1.ControlChange( Sender: TObject );
begin
  SyncWithRechner;
end;

procedure TForm1.FormShow( Sender: TObject );
begin
  LoadFromRechner;
end;

procedure TForm1.LoadFromRechner;
begin
  if FIsLoading
  then
    Exit;

  FIsLoading := True;
  try
    Edit1.Text := FRechner.Wert1;
    Edit2.Text := FRechner.Wert2;
    Edit3.Text := FRechner.Wert3;
    Edit4.Text := FRechner.Wert4;
    Label1.Caption := FRechner.Ergebnis1;
    Label2.Caption := FRechner.Ergebnis2;

    if FRechner.Wert3Berechnet
    then
      Edit3.Font.Color := clRed
    else
      Edit3.ParentFont := True;
  finally
    FIsLoading := False;
  end;
end;

procedure TForm1.SaveToRechner;
begin
  if FIsLoading
  then
    Exit;

  FRechner.Wert1 := Edit1.Text;
  FRechner.Wert2 := Edit2.Text;
  FRechner.Wert3 := Edit3.Text;
  FRechner.Wert4 := Edit4.Text;
end;

procedure TForm1.SyncWithRechner;
begin
  SaveToRechner;
  LoadFromRechner;
end;

end.
Angehängte Dateien
Dateityp: zip dp_182807.zip (838,2 KB, 6x aufgerufen)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:53 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz