(ERLEDIGT)"Vom Benutzer geändert"-Ereignis für TField?

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
Soner
Beiträge: 411
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: 32Bit
Wohnort: Hamburg

(ERLEDIGT)"Vom Benutzer geändert"-Ereignis für TField?

Beitrag von Soner »

Es ist immer unmöglich ohne Umwege zu unterschieden wer das Feld geändert hat. z.B. Benutzer über TDBCheckbox oder ich selber per Code?
TField.OnChange wird bei jede Feldänderung aufgerufen und das Ereignis TField.OnSetText wird von Datenbank-Controls nicht konsequent benutzt.
Ich überlege TField wie folgt dafür zu Erweitern. TField bekoment eine Prozedur ChangeValue und ein Ereignis OnChangeValue.
ChangeValue wird nur von "data controls" aufgerufen und das Ereignis OnChangeValue wird von ChangeValue aufgerufen.

Code: Alles auswählen

 
{
TField.ChangeValue wird von "data controls" z.B. von TDBCheckBox aufgerufen.
  Bedeutung von Variablen:
    AAllowed: Änderung erlaubt
    AValueChanged: Übergebene Daten(AValue) wurden in ChangeValue geändert,
                  darauf kann Aufrufer sich selbt Aktualisieren. z.B. Lange Text abgeschnitten usw. 
    AValue: Feldwert
}

procedure TField.ChangeValue(var AAllowed, AValueChanged: Boolean; AValue: Variant);
 
 
type
  TFieldChangeValueEvent: procedure(Sender: TField; var AAllowed, AValueChanged: Boolean; AValue: Variant) of object;
 
 


Ich werde danach alle "Data Controls" von Lazarus ändern, damit ich nur OnChangeValue-Event auswerten kann.

Was haltet ihr von der Idee?
Habe ich etwas vergessen, fehlt etwas oder erfinde ich das Rad neu?
Zuletzt geändert von Soner am Fr 16. Mär 2018, 21:45, insgesamt 2-mal geändert.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von mse »

In MSEgui haben alle Edit- und DBEdit-Widgets die Eigenschaften "OnSetvalue" und "OnDataEntered".
"OnSetvalue" hat die Signatur

Code: Alles auswählen

 
procedure(const sender: TObject; var avalue: <typ der value eigenschaft>;  var accept: Boolean) of object;
 

und wird aufgerufen, wenn der Anwender eine Eingabe tätigt. "avalue" kann verändert werden und/oder der Wert kann durch Setzen von accept auf false zurückgewiesen werden.
In OnSetValue hat die "Value"-Eigenschaft des widgets den ursprünglichen Wert. Wir die Eingabe akzeptiert, wird "avalue" in "<editwidget>.Value" gespeichert und "OnDataEntered" aufgerufen. "OnDataEntered hat die Signatur

Code: Alles auswählen

 
procedure(const sender: TObject) of object;
 

Zudem hat jedes Edit-widget die Eigenschaft "ifiLink" wo eine entsprechende ifiLink-Komponente eingehängt werden kann um zentral auf Werteänderungen zu reagieren und Werte zu setzen.
Ob man in TField zwischen Anwender- und Programmeingabe unterscheiden sollte bin ich mir nicht sicher. Ich meine eher nicht , da User-Interaktion nicht auf der Daten-Ebene abgehandelt werden sollte.

Soner
Beiträge: 411
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: 32Bit
Wohnort: Hamburg

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von Soner »

Deine Lösung ist auch nicht schlecht. Aber wenn man es in TField macht, dann ist es zentral auf einer Stelle, man kann dann die Datenverarbeitung von GUI komplett trennen. Und manchmal wird ein Feld von verschiedenen Widgets bearbeitet, man mußte dann für jeden Widget das Ereignis behandeln.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von mse »

Für diesen Fall gibt es die ifi-Schnittstelle. Oder man benutzt den selben handler in mehreren widgets oder eine zentrale Behandlungs-Routine. Das ganze TField-TDatalink-TDatasource-TDataset-System ist kompliziert genug, ich wäre mit Erweiterungen zurückhaltend.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 4182
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von af0815 »

Vielleicht wäre hier ein 'Patch' angebracht :

Code: Alles auswählen

TField.OnSetText wird von Datenbank-Controls nicht konsequent benutzt

anstatt eine neue Schnittstelle zu machen, die uU. dasselbe Ziel hat.

Andreas
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Soner
Beiträge: 411
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: 32Bit
Wohnort: Hamburg

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von Soner »

af0815 hat geschrieben:Vielleicht wäre hier ein 'Patch' angebracht :

Code: Alles auswählen

TField.OnSetText wird von Datenbank-Controls nicht konsequent benutzt

anstatt eine neue Schnittstelle zu machen, die uU. dasselbe Ziel hat.

Andreas


Das habe ich auch überlegt, aber eigentlich ist ja OnSetText gar nicht dafür gedacht. Nur weil bei der Erklärung „user-formatted“ steht, habe ich es damals falsch interpretiert. https://www.freepascal.org/docs-html-3.0.0/fcl/db/tfield.onsettext.html
Außerdem scheint mir sinnlos, nicht String-Typen wie TdateTime oder Zahlen hin und her zu konvertieren. Wenn die Lazarus- und Freepascal-Entwickler meinen Vorschlag akzeptieren, dann kann ich auch dafür Patch reichen. Dann hatten wir eindeutiges Ereignis um auf Benutzeränderungen zu reagieren.

mse hat geschrieben:Für diesen Fall gibt es die ifi-Schnittstelle. Oder man benutzt den selben handler in mehreren widgets oder eine zentrale Behandlungs-Routine. Das ganze TField-TDatalink-TDatasource-TDataset-System ist kompliziert genug, ich wäre mit Erweiterungen zurückhaltend.

Ich habe schon TField nachgeschaut es sind ca 3-5 neue Zeilen plus die Änderungen von "Data Controls".
Das Problem ist nur, dass meine Änderungsliste immer länger wird. Ich überlege von Lazarus und Freepascal fork zu machen :D .

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2261
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.8, FPC 3.0.4)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von m.fuchs »

Soner hat geschrieben:Ich überlege von Lazarus und Freepascal fork zu machen :D .

Warum fällt mir da sofort das Leben des Brian ein? Judäische Volksfront, Volksfront von Judäa, Populäre Front... :wink:
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von mse »

Soner hat geschrieben:Ich habe schon TField nachgeschaut es sind ca 3-5 neue Zeilen plus die Änderungen von "Data Controls".

Bleibt die Frage, ob UI-Ereignisse in TField etwas zu suchen haben. Warum nicht, TField.FocusControl() gibt es ja auch.
In MSEgui existiert die Event-Verbindung editwidget -> tfield über "iifiserver" bereits:

Code: Alles auswählen

 
 tfieldsdatalink = class(tmsedatalink,iifiserver)
  protected
   procedure activechanged; override;
   procedure layoutchanged; override;
   procedure updatefields; virtual;
   procedure fieldchanged; virtual;
    //iifiserver
   procedure execute(const sender: iificlient); virtual;
   procedure valuechanged(const sender: iificlient); virtual;
   procedure statechanged(const sender: iificlient;
                            const astate: ifiwidgetstatesty); virtual;
   procedure setvalue(const sender: iificlient;
                var avalue; var accept: boolean; const arow: integer); virtual; <<<----
   procedure dataentered(const sender: iificlient;
                                                 const arow: integer); virtual; <<<----
   procedure closequery(const sender: iificlient;
                             var amodalresult: modalresultty); virtual;
   procedure sendmodalresult(const sender: iificlient;
                             const amodalresult: modalresultty); virtual;
   procedure updateoptionsedit(var avalue: optionseditty); virtual;
 end;
 
 tfielddatalink = class(tfieldsdatalink)
[...]
 

setvalue() und dataentered() könnten in tfielddatalink überschrieben werden um die entsprechenden events in TField aufzurufen. Ich werde mal schauen, ob es sich machen lässt.

Soner
Beiträge: 411
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: 32Bit
Wohnort: Hamburg

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von Soner »

m.fuchs hat geschrieben:
Soner hat geschrieben:Ich überlege von Lazarus und Freepascal fork zu machen :D .

Warum fällt mir da sofort das Leben des Brian ein? Judäische Volksfront, Volksfront von Judäa, Populäre Front... :wink:

Weil beides unsinnig ist. Das war scherz gemeint, deshalb auch similey. Als ich es geschrieben habe, ist mir Teenager eingefallen, die für ihr Linux tolles Desktophintergrund oder Thema finden und daraus Distribution machen :lol:

mse hat geschrieben:Ich werde mal schauen, ob es sich machen lässt.

Wenn bei MSE-Widgets "OnSetvalue" oder "OnDataEntered" nur bei User-Änderungen aufgerufen werden, dann würde ich nicht ähnliches nochmal erstellen, das macht es kompliezierter.

Ich habe mir das so vorgestellt, bei TField:

Code: Alles auswählen

 
type
  TFieldChangeValueEvent = procedure(Sender: TField; var AAllowed, AValueChanged: Boolean; var AValue: Variant) of object;
  TField = class(TComponent)
  //...
  public
    procedure ChangeValueprocedure(var AAllowed, AValueChanged: Boolean; var AValue: Variant);
  published
    OnChangeValue: TFieldChangeValueEvent;
  end;
 
procedure TField.ChangeValue(var AAllowed, AValueChanged: Boolean; var AValue: Variant);
begin
   if Assigned(OnChangeValue) then OnChangeValue(self, AAllowed, AValueChanged, AValue);
   if AAllowed then SetVarValue(AValue);
end;
 



Und bei allen DB-Controls wo AsString:=XY oder Text:=XY gibt das verwenden:

Code: Alles auswählen

 
  Field.ChangeValue(AAllowed, AValueChanged, AValue);
  if AValueChanged then SichSelbstAktualisieren;
 



Mann konnte Field.ChangeValue auch manuell aufrufen, z.B. bei Webapplikationen um vom Server übermitellelte Daten zu prüfen.
Vorteil bei so etwas ist, dass nicht alle Daten auf falsche eingeben überprüft werden.
Vielleicht muss noch Event und Prozedur anders bennant werden damit unterschied sichtbar wird. Irgendwie muss ich das Wort "User" einbauen.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von mse »

Soner hat geschrieben:
mse hat geschrieben:Ich werde mal schauen, ob es sich machen lässt.

Wenn bei MSE-Widgets "OnSetvalue" oder "OnDataEntered" nur bei User-Änderungen aufgerufen werden, dann würde ich nicht ähnliches nochmal erstellen, das macht es kompliezierter.

Ich habe es mal versuchsweise eingefügt, die Verbindung existiert ja bereits.
git master 2445ed29aa1fbe89b193a8b752eaba8d205b0b3e
https://gitlab.com/mseide-msegui/mseide-msegui
Ich habe mir das so vorgestellt, bei TField:
[...]

Denke daran, dass die bestehenden Events in der gewohnten Reihenfolge und mit der gewohnten Funktionalität aufgerufen werden müssen. Auch muss z.B. Esc bei nicht akzeptiertem Wert den ursprünglichen Wert rekonstruieren.
Ich versuche nach Möglichkeit die Verwendung von Variant zu vermeiden.

Soner
Beiträge: 411
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: 32Bit
Wohnort: Hamburg

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von Soner »

@mse
Deine Änderungen habe ich hier gesehen: https://gitlab.com/mseide-msegui/mseide-msegui/commit/2445ed29aa1fbe89b193a8b752eaba8d205b0b3e

Dort habe ich interessantes entdeckt:
"
procedure setvalue(const sender: iificlient; var avalue; var accept: boolean; ...

Variable ohne Typ-Angabe :shock:
Ich wußte gar nicht das wir das können, ic habe getestet, es funktioniert überall. Das werde ich ab jetzt bestimmt öfters nutzen.
-
Variante-Typen habe auch meistens vermieden, aber ich glaube es ist besser als IntToStr<-->StrToInt, DateToStr<-->StrToDate, usw.
Heute habe ich Geschwindigkeitsvergleich bei Zuweisungen von native Typ zu native Typ und native Typ zu Variant gemacht. Es gibt kaum Unterschiede, nur Integer zu Integer ist fast doppelt so schnell wie Integer zu Variant.

Soner
Beiträge: 411
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: 32Bit
Wohnort: Hamburg

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von Soner »

Eigentlich wollte ich von euch wissen was ihr von Idee haltet, ob ich "patch/feature request" reichen soll.
Aber da es niemanden von Lazarus-Benutzern interessiert, nehme ich an, dass davon Freepascal/Lazarus-Entwickler auch nicht begeistert sein werden. Deshalb mache ich das privat und werde kein Patch reichen.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: "Vom Benutzer geändert"-Ereignis für TField?

Beitrag von mse »

Soner hat geschrieben:Variante-Typen habe auch meistens vermieden, aber ich glaube es ist besser als IntToStr<-->StrToInt, DateToStr<-->StrToDate, usw.

Einverstanden, das ist natürlich noch ungünstiger.

Antworten