AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi OnChange-Verarbeitung bei eigenem Edit-Objekt
Thema durchsuchen
Ansicht
Themen-Optionen

OnChange-Verarbeitung bei eigenem Edit-Objekt

Ein Thema von jokeBB · begonnen am 20. Apr 2010 · letzter Beitrag vom 20. Apr 2010
Antwort Antwort
jokeBB

Registriert seit: 7. Okt 2009
Ort: Böblingen
10 Beiträge
 
Delphi 2010 Professional
 
#1

OnChange-Verarbeitung bei eigenem Edit-Objekt

  Alt 20. Apr 2010, 17:35
Hallo,
folgendes Problem (OOP-Anfänger ): wie kann ich bei eigenen Edit-Objekten sowohl im Objekt als auch außerhalb (im Formular) auf OnChange reagieren?

Konkret: da ich in einem Formular viele Eingabefelder mit angrenzenden Textfeldern und besonderem Verhalten brauche, habe ich mir ein eigenes Objekt hierfür gemacht

Delphi-Quellcode:
type TInputBlock = class(TEdit)
  private
    FEdit: TEdit;
    ...
  protected
    procedure edtChange(Sender: TObject);
    ...
  public
    constructor Create(InputData: TInputData; InputDDName: TInputDDNames);
    procedure ShowBox(parent: TWinControl; col: integer);
    //procedure OnChange2(Sender: TObject);
    ...
end;

procedure TInputBlock.ShowBox(parent: TWinControl; col: integer);
begin
...
FEdit:=TEdit.Create(FPanel);
FEdit.Parent:=FPanel;
FEdit.Name := 'edt_'+IntToStr(col);
FEdit.SetBounds(120,2,60,20);
FEdit.Text := dd2s(FInputData[FInputDDName],-1);
FEdit.OnEnter := edtEnter;
FEdit.OnExit := edtExit;
FEdit.OnKeyPress := edtKeyPress;
FEdit.OnChange := edtChange;
...
end;


procedure TInputBlock.edtChange(Sender: TObject);
var dd: Double;
begin
if s2dd(FEdit.Text,dd) then
  begin
  // erfolgreiche Umwandlung in Double => Wert speichern
  FInputData[FInputDDName] := dd;
  FEdit.Color:= clYellow;
  ...
  end else begin
  // Umwandlung fehlgeschlagen
  FEdit.Color:= clRed;
  end;
end;

//procedure TInputBlock.OnChange2(Sender: TObject);
//begin
// edtChange(Sender);
//end;
Im FormCreate meines Formulars werden diese InputBoxen jetzt instantisiert und gezeichnet (kann man sicherlich auch zusammenfassen, aber egal):

Delphi-Quellcode:
inpX := TInputBlock.Create(myData,iTS);
inpX.ShowBox(scrInput, col);
...
Soweit klappt das gut: kann im Formular viele Felder erzeugen, die ihre Werte bei Eingabe automatisch prüfen und wegsichern bzw Fehleingaben verhindern und durch Farbe kennzeichnen, also jedes Feld für sich verarbeitet intern das OnChange über edtChange.

Allerdings müssen die Boxen untereinander Wechselwirkung haben, d.h. bei Eingabe/Auswahl bestimmter Werte z.B. in Box inpX (Comboboxen kommen noch) muss sich der Inhalt von Box inpY und inpZ entsprechend anpassen. Also sollte ich im Formular ebenfalls auf OnChange reagieren, aber natürlich das Basisverhalten der Box behalten/erben.

Ich dachte mir, ich könne im Formular eine eigene, zentrale Procedure machen, die ich dem OnChange jeder Box zuweise und die somit zuerst durchlaufen wird, und dann aber seinerseits die jeweilige Original-Routine aufruft (daher auch mal der Versuch mit OnChange2, um OnChange nicht zu überschreiben)


Delphi-Quellcode:
inpX.OnChange := InputChanged;
...

procedure TFormSingle.InputChanged(Sender: TObject);
begin
...
if Sender is TInputBlock then TInputBlock(Sender).OnChange(Sender);
...
end;
Aber leider wird immer noch die edtChange direkt durchlaufen, die InputChanged wird gar nicht erst aufgerufen.

Wo liegt der Denkfehler, kann mir da jemand vielleicht bitte einen Tipp geben?

Gruß, jokeBB
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

Re: OnChange-Verarbeitung bei eigenem Edit-Objekt

  Alt 20. Apr 2010, 17:47
[edit]
Jetzt seh ich das gerade...

Deine Komponente ist ein "TEdit" und sie erzeugt intern nochmals ein TEdit, welches sie aber extern verwalten läßt, von einem femden TPanel, welches als Parent und Owner des Edits fungiert .... wieso?
Somit sind es ja nun 2 Edits.
TInputBlock erzeugt das Edit, also sollte das Edit auch dessen Besitz bleiben.



Wenn du den Namen nicht wirklich brauchst, dann weiße .Name nichts zu.
Das erspart dir später mal Probleme, falls schon eine gleichnamige Komponente existieren sollte.
[/edit]



Überschreibe in deiner Komponente dieses:
Delphi-Quellcode:
TInputBlock = class(TCustomEdit)
protected
  procedure Change; override;
end;

procedure TInputBlock.Change;
begin
  ...
  inherited;
end;
Das Change entspricht dem OnChange.

Über die Methode Change hast du dann die interne Rückmeldung über das Change-Ereignis
und über das Property OnChange wäre das Ereignis weiterhin extern verfügbar.


PS: Idealer Weise leitet man soeine Komponente von TCustomEdit ab.
Somit hat man mehr Kontrolle über die Freigaben und TCustomEdit wurde auch ja extra für sowas Eingeführt.
Schau dir einfach mal an, wie TEdit definiert ist, dann siehst du vielleicht schon, was gemeint ist.
$2B or not $2B
  Mit Zitat antworten Zitat
jokeBB

Registriert seit: 7. Okt 2009
Ort: Böblingen
10 Beiträge
 
Delphi 2010 Professional
 
#3

Re: OnChange-Verarbeitung bei eigenem Edit-Objekt

  Alt 20. Apr 2010, 21:21
Zunächst mal danke für die Antwort.

Zu dem doppelten TEdit und dem Panel als Owner: zunächst hatte ich mein Objekt nur von TObject abgeleitet. In diesem Objekt wurden als Kernelement das TEdit, aber auch weitere Label, Panel u.a. erzeugt. Alles zusammen habe ich auf ein Panel gepackt, so dass ich die Positionen immer nur innerhalb des Panels angeben musste. Hatte soweit schon alles funktioniert. Um dann aber dem gesamten TInputBlock ein OnChange zu vererben, habe ich ihn von TEdit statt von TObject abgeleitet. Funktionell hat sich nichts geändert, aber das TInputBlock.OnChange war verfügbar. Ok, war vielleicht keine so geniale Idee... bezieht sich das OnChange jetzt auf das falsche TEdit?

Ich probier mal aber auf jeden Fall mit deinem Vorschlag weiter.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

Re: OnChange-Verarbeitung bei eigenem Edit-Objekt

  Alt 20. Apr 2010, 21:36
Zitat von jokeBB:
Zu dem doppelten TEdit und dem Panel als Owner: zunächst hatte ich mein Objekt nur von TObject abgeleitet.
Eine Komponente sollte natürlich von TComponent abgeleitet sein.

Leite deinen TInputBlock von TPanel ab und positioniere seine Objekte (Edit, Label und Co.) in diesem.
(vielleicht noch den Rahmen des Panels im Constructor verstecken)

Dann verpaß deinem TInputBlock ein neues öffentliches Property OnChange und eine interne Methode Change.

Das Edit wird dann im Constructor erstellt und Owner, sowie Parent auf Self gesetzt.
(freigeben mußt du das Edit nicht, denn darum kümmert sich ja der Owner, also die Inputbox selber, wenn diese freigegeben wird)

Change wird dann den eigenen Edits (also denen innerhalb der InputBox) als Edit.OnChange zugewiesen.

In TInputBlock.Change kommt dannnoch ein
if Assigned(FOnChange) then FOnChange(Self); Wird nun eines der Edits verändert, dann kann die Komponente (TInputBlock) dort darauf reagieren und falls der TInputBlock ein OnChange von außerhalb zugewiesen wurde, dann wird auch dieses aufgerufen.
$2B or not $2B
  Mit Zitat antworten Zitat
jokeBB

Registriert seit: 7. Okt 2009
Ort: Böblingen
10 Beiträge
 
Delphi 2010 Professional
 
#5

Re: OnChange-Verarbeitung bei eigenem Edit-Objekt

  Alt 20. Apr 2010, 22:29
Cool, es funktioniert! Vielen Dank! Ich hab's zwar immer noch nicht so ganz geblickt, wer hier was von wem und überhaupt erbt, aber irgendwann kommt das auch noch. Wenn man's blickt, ist OOP doch irgendwie eine nette Sache...

P.S.
FEdit:=TEdit.Create(Self); FEdit.Parent:=Self; hatte ich entsprechend deiner Empfehlung auch probiert, gab aber Schutzverletzung

Falls es jemand interessiert (und jemand genauso lange grübelt wie ich), hier die Langform...

Delphi-Quellcode:
type TInputBlock = class(TPanel)
  private
    FPanel: TPanel;
    FEdit: TEdit;
    FOnChange: TNotifyEvent;
    ...
  protected
    procedure Change(Sender: TObject);
    ...
  public
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
    constructor Create(InputData: TInputData; InputDDName: TInputDDNames; parent: TWinControl; col: integer);
    ...
end;

...

constructor TInputBlock.Create(InputData: TInputData; InputDDName: TInputDDNames; parent: TWinControl; col: integer);
begin
...
FPanel:= TPanel.Create(parent);
FPanel.Parent := parent;
FPanel.SetBounds(0,(col-1)*25,250,25);
...
FEdit:=TEdit.Create(FPanel);
FEdit.Parent:=FPanel;
FEdit.SetBounds(120,2,60,20);
FEdit.Text := dd2s(FInputData[FInputDDName],-1);
FEdit.OnChange := Change;
...
end;

...

procedure TInputBlock.Change;
var dd: Double;
begin
if s2dd(FEdit.Text,dd) then
  begin
  // erfolgreiche Umwandlung in Double => Wert speichern
  FInputData[FInputDDName] := dd;
  FEdit.Color:= clYellow;
  ...
  end else begin
  FEdit.Color:= clRed;
  ...
  end;
if Assigned(FOnChange) then FOnChange(Self);
inherited;
end;

...
Sowie im Form

Delphi-Quellcode:
procedure TFormSingle.FormCreate(Sender: TObject);
begin
...
inpX := TInputBlock.Create(myData,iTS,scrInput, col);
inpX.OnChange := InputChanged;
...
end;

procedure TFormSingle.InputChanged(Sender: TObject);
begin
...
Label1.Caption := 'Test';
...
end;
Ergebnis: bei einer Änderung des Eingabefeldes wird zuerst die "innere" Routine (z.B. für die Eingabeprüfung) und dann die "äußere" (z.B. um andere Felder zu ändern) durchlaufen
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

Re: OnChange-Verarbeitung bei eigenem Edit-Objekt

  Alt 20. Apr 2010, 22:47
Wie gesagt, TInputBlock ist ja nun selber das Panel, also wenn man es richtig initialisiert.

Delphi-Quellcode:
type TInputBlock = class(TPanel)
  private
    FEdit: TEdit;
    FOnChange: TNotifyEvent;
    ...
  protected
    procedure Change(Sender: TObject);
    ...
  public
    constructor Create(Owner: TWinControl; InputData: TInputData; InputDDName: TInputDDNames; col: integer);
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
    ...
end;

...

constructor TInputBlock.Create(OwnerAndParent: TWinControl; InputData: TInputData; InputDDName: TInputDDNames; col: integer);
begin
inherited create(OwnerAndParent);
Parent := OwnerAndParent;
SetBounds(0,(col-1)*25,250,25);
...
FEdit:=TEdit.Create(Self);
FEdit.Parent:=Self;
FEdit.SetBounds(120,2,60,20);
FEdit.Text := dd2s(FInputData[FInputDDName],-1);
FEdit.OnChange := Change;
...
end;

...

procedure TInputBlock.Change;
var dd: Double;
begin
if s2dd(FEdit.Text,dd) then
  begin
  // erfolgreiche Umwandlung in Double => Wert speichern
  FInputData[FInputDDName] := dd;
  FEdit.Color:= clYellow;
  ...
  end else begin
  FEdit.Color:= clRed;
  ...
  end;
if Assigned(FOnChange) then FOnChange(Self);
inherited;
end;

...

procedure TFormSingle.FormCreate(Sender: TObject);
begin
...
inpX := TInputBlock.Create(scrInput, myData,iTS, col);
inpX.OnChange := InputChanged;
...
end;

procedure TFormSingle.InputChanged(Sender: TObject);
begin
...
Label1.Caption := 'Test';
...
end;
$2B or not $2B
  Mit Zitat antworten Zitat
jokeBB

Registriert seit: 7. Okt 2009
Ort: Böblingen
10 Beiträge
 
Delphi 2010 Professional
 
#7

Re: OnChange-Verarbeitung bei eigenem Edit-Objekt

  Alt 20. Apr 2010, 22:54
ah, ok, klar - wie du schon schreibst "wenn man es richtig macht"...
  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 15:02 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