Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Focus-Problem bei Firemonkey (https://www.delphipraxis.net/169822-focus-problem-bei-firemonkey.html)

eddie11 14. Aug 2012 12:22

Focus-Problem bei Firemonkey
 
Hi allerseits,

ich möchte nach der Eingabe in einem Edit-Feld den Inhalt überprüfen. Das mach ich im OnExit-Ereignis des Edit-Controls:
Code:
procedure TForm1.Edit1Exit(Sender: TObject);
begin
  if Edit1.Text<>'xx' then begin
    ShowMessage('Error: <>xx');
    Edit1.SetFocus();
  end;
end;
- ich Prüfe ich in meinem Beispiel auf 'xx' ab,
- im Fehlerfall setze ich den Focus zurück auf das Edit-Feld

die Prüfung funktioniert: es kommt die Fehlermeldung
anschließend wird der Focus aber NICHT auf das Edit-Feld gesetzt, sondern das Feld, welches das Verlassen des Edit-Feldes veranlasst hat, hat jetzt den Focus. Das gleiche Beispiel in VCL funktioniert einwandfrei. Ist das ein Bug in Firemonkey oder muss ich da irgend etwas anders machen?

danke

mkinzler 14. Aug 2012 12:30

AW: Focus-Problem bei Firemonkey
 
Zitat:

welches das Verlassen des Edit-Feldes veranlasst hat
? :gruebel:

Btw. nimm besser Sender statt Edit1

eddie11 14. Aug 2012 12:54

AW: Focus-Problem bei Firemonkey
 
naja, vielleicht habe ich mich ein bisschen undeutlich ausgedrückt, ich versuchs nochmal:

Ich habe auf der Form zwei Edit-Felder, Edit1 und Edit2. Wenn Edit1 den Focus hat und ich dann auf Edit2 klicke, dann wird das OnExit von Edit1 aufgerufen (Prüfung), Edit2 ist also das Feld, welches "das Verlassen des EditFeldes veranlasst" hat. Aufgrund der negativen Prüfung auf "xx" soll der Focus wieder zurück auf Edit1 - das passiert aber nicht, Edit2 hat jetzt den Focus. Ich möchte aber, dass der Focus von Edit1 nur dann weg ist, wenn die Eingabeprüfung ok war.

Zitat:

Btw. nimm besser Sender statt Edit1
warum?

Klaus01 14. Aug 2012 12:56

AW: Focus-Problem bei Firemonkey
 
Hallo,

Edit1.setFokus gibt es bei FM nicht?

Grüße
Klaus

eddie11 14. Aug 2012 12:59

AW: Focus-Problem bei Firemonkey
 
Zitat:

Edit1.setFokus gibt es bei FM nicht?
doch, funktioniert auch üblicherweise. Aber in der oben beschriebenen Konstellation wird es anscheinend irgendwie ignoriert, bzw. die Aktivierung des zweiten Feldes wird erst danach durchgeführt.

mkinzler 14. Aug 2012 13:00

AW: Focus-Problem bei Firemonkey
 
Zitat:

Zitat von eddie11 (Beitrag 1178200)
naja, vielleicht habe ich mich ein bisschen undeutlich ausgedrückt, ich versuchs nochmal:

Ich habe auf der Form zwei Edit-Felder, Edit1 und Edit2. Wenn Edit1 den Focus hat und ich dann auf Edit2 klicke, dann wird das OnExit von Edit1 aufgerufen (Prüfung), Edit2 ist also das Feld, welches "das Verlassen des EditFeldes veranlasst" hat. Aufgrund der negativen Prüfung auf "xx" soll der Focus wieder zurück auf Edit1 - das passiert aber nicht, Edit2 hat jetzt den Focus. Ich möchte aber, dass der Focus von Edit1 nur dann weg ist, wenn die Eingabeprüfung ok war.

Zitat:

Btw. nimm besser Sender statt Edit1
warum?

Weil
-die Methode dann auch für andere Edits funktioniert
-auch nach Ändern der Bezeichnung des Edits funktioniert
-auch für andere Komponenten nutzbar ist
...

eddie11 14. Aug 2012 13:03

AW: Focus-Problem bei Firemonkey
 
Zitat:

Weil
-die Methode dann auch für andere Edits funktioniert
-auch nach Ändern der Bezeichnung des Edits funktioniert
-auch für andere Komponenten nutzbar ist
...
ok, das ist klar, mach ich auch üblicherweise so
ist ja nur ein Beispiel...

Insider2004 14. Aug 2012 15:21

AW: Focus-Problem bei Firemonkey
 
VCL <> FMX (leider). Schreibe eine Fehlermeldung in QC.

himitsu 14. Aug 2012 15:39

AW: Focus-Problem bei Firemonkey
 
Und so?
Delphi-Quellcode:
procedure TForm1.Edit1Exit(Sender: TObject);
begin
  if Edit1.Text<>'xx' then begin
    ShowMessage('Error: <>xx');
    Edit1.SetFocus();
    Abort;
  end;
end;
Eventuell wird ja erst verlassen (inkl. OnExit) und dann betreten, womit dann im FMX das Setzen des Fokus nach deinem Zurücksetzen passieren würde.

Abort hilft aber nur, wenn kein Try-Finally drumrum ist, wo erst im Finally-Block der Fokus gesetzt wird, bzw. wenn in einem drumrumliegenden Try-Except nicht die stille Abort-Exception beachtet wird (welches gerne vergessen wird, womit dann der Abbruchvorgang vorzeitig abbricht).

eddie11 15. Aug 2012 06:08

AW: Focus-Problem bei Firemonkey
 
ja geil, das hat es gebracht. Nach dem ABORT wird keine weitere Aktion (Focus setzen) mehr ausgeführt. Das funktioniert also in meinem Sinne. Nur der Cursor ist dann weg :shock: aber den krieg ich schon irgendwie wieder.

Danke vielmals :bounce2::bounce2::bounce2:

jaenicke 15. Aug 2012 07:50

AW: Focus-Problem bei Firemonkey
 
Das funktioniert, weil der Fokus tatsächlich erst nach dem Event gesetzt wird, ebenso wie die UI-Effekte usw.
Eine schöne Lösung ist das aber wohl nicht, denn wie die Folgefehler mit dem fehlenden Cursor zeigt ist das so nicht gedacht gewesen.

Leider kommt man da aber auch kaum heran. Die Prozedur SetFocusControl des Formulars (habs grad nicht mehr so genau im Kopf) ist z.B. natürlich wieder nicht virtuell. (Sonst wäre es ja zu einfach da etwas zu ändern... :roll:) Diese Designprobleme ziehen sich leider auch durch Firemonkey durch (das Problem gibt es ja in der VCL genauso). Immer nur das ist virtuell was gerade jemand an anderer Stelle gebraucht hat. An die Programmierer, die später damit arbeiten, wird offenbar weniger gedacht.

Eine Lösung:
SetFocusControl asynchron nach dem Ende der Prozedur aufrufen um den Fokus zurückzusetzen. In der VCL hätte ich mir dazu selbst eine Windows Message geschickt. In Firemonkey fällt mir gerade keine schöne Lösung dafür ein.

RWarnecke 15. Aug 2012 07:57

AW: Focus-Problem bei Firemonkey
 
Ich habe es jetzt nicht ausprobiert, aber was ist, wenn der Wert von Edit 1 erst im OnEnter von Edit 2 überprüft wird.

eddie11 15. Aug 2012 09:13

AW: Focus-Problem bei Firemonkey
 
Zitat:

Die Prozedur SetFocus oder so des Formulars (habs grad nicht mehr so genau im Kopf) ist z.B. natürlich wieder nicht virtuell.
Das war auch mein Ansatz aber wie gesagt, SetFocusControl (so heißt die Prozedur) ist leider nicht virtuell.

Zitat:

Ich habe es jetzt nicht ausprobiert, aber was ist, wenn der Wert von Edit 1 erst im OnEnter von Edit 2 überprüft wird.
Das wird der Weg sein, den ich gehen werde.
Da ich alle Forms von einer eigenen BasisForm erben lasse, kann ich ein eigenes Property "FocusedControl" einbauen. Dieses Property wird dann beim OnEnter eines Controls gesetzt. Im Setter der Property (in der Form) wird dann die EingabePrüfung für das zuvor aktiv gewesene Control durchgeführt.

himitsu 15. Aug 2012 09:27

AW: Focus-Problem bei Firemonkey
 
Wegen der UI-Efekte bräuchte man doch einfach nur ein Neuzeichnen des UI veranlassen. :gruebel:

Zitat:

Ich habe es jetzt nicht ausprobiert, aber was ist, wenn der Wert von Edit 1 erst im OnEnter von Edit 2 überprüft wird.
Ein Problem dabei ist ja, daß man dann anstatt in einem OnExit man nun in allen OnEnter, jeder einzelnen Komponente auf der Form prüfen müßte und das dann womöglich auch noch abhängig von der Komponente, welche davor fokusiert war,
denn man kann ja von Edit1 nicht nur zu Edit2 wechseln. (rückwärts tabben und dann gibt's och noch die Maus)

Da muß Emba unbedingt noch etwas nacharbeiten, oder sie bieten ein OnFocusChange-Event in der Form an, wo man die alte und neue Komonente erfährt und wo man z.B. ein Accept-Flag setzen kann.



In der Zwischenzeit könnte man sich höchstens noch eine SetFocus-Prozedur schreiben, welche den Fokus setzt, die "fehlenden" UI-Ereignisse auslöst und dann mit Abort abbricht.

eddie11 15. Aug 2012 12:39

AW: Focus-Problem bei Firemonkey
 
also nach einer ziemlich langen Rumprobiererei bin ich zu dem Schluss gekommen, dass das so nicht funzen kann. Es scheint ziemlich aussichtslos, eine vernünftige Eingabe-Validierung direkt nach der Eingabe zu machen - das ist aber am Besten füe den Anwender!

Dazu kommt noch, dass Memory-Leaks erzeugt werden, wenn man im OnExit oder OnEnter eines Controls den Fokus auf ein anderes Control setzt...

Aber mal ne andere Frage:

Wie macht Ihr das denn so mit der Eingabe-Validierung?

jaenicke 15. Aug 2012 12:53

AW: Focus-Problem bei Firemonkey
 
Ich markiere in Rot oder mit einem Hinweisfähnchen inkl. kurzer Erklärung (je nach GUI), lasse aber in der Regel den Fokus unberührt um den Arbeitsfluss nicht unnötig zu stören. So sieht der User, dass etwas nicht in Ordnung ist, kann aber erst einmal weitermachen oder direkt zurück und korrigieren, ganz nach Wunsch.

Die einzige wirklich saubere Lösung für dein Vorhaben wäre wie schon geschrieben den Fokus nach dem Event zurückzusetzen, wenn SetFocusControl schon durch ist. Wie das bei Firemonkey am besten geht, weiß ich nicht.

bernau 15. Aug 2012 14:47

AW: Focus-Problem bei Firemonkey
 
Zitat:

Zitat von jaenicke (Beitrag 1178366)
Ich markiere in Rot oder mit einem Hinweisfähnchen inkl. kurzer Erklärung (je nach GUI), lasse aber in der Regel den Fokus unberührt um den Arbeitsfluss nicht unnötig zu stören. So sieht der User, dass etwas nicht in Ordnung ist, kann aber erst einmal weitermachen oder direkt zurück und korrigieren, ganz nach Wunsch.

So mache ich das bei meiner Software auch. Grade wenn "blind" eingegeben wird, ist es ärgerlich wenn man immer im gleichen Feld hängen bleibt. Und bei Eingabe großen Datenmengen kommt die blinde Eingabe oft vor.

himitsu 15. Aug 2012 15:44

AW: Focus-Problem bei Firemonkey
 
Bei FM kann man ja nun ganz leicht einen knallroten Schein um die betreffenden Eingabeelemente machen.

eddie11 16. Aug 2012 09:39

AW: Focus-Problem bei Firemonkey
 
ok, das mit dem Markieren gefällt mir gut, das werde ich dann auch so machen. Die endgültige Prüfung muss dann bei Drücken von "Ok" oder sonstiger weiterer Verarbeitung nochmals alles Validieren und dann ggf. einen entsprechenden Hinweis bringen. Allerdings hätte ich es lieber, wenn direkt nach der Eingabe ein Hinweis käme ohne den es nicht weiter geht. Oft sind die Eingaben einzelner Felder voneinander abhängig (z.B. Postleitzahl, Ort und Straßen) - aber wenns nicht mit überschaubarem Aufwand hinzukriegen ist...

jaenicke 16. Aug 2012 10:56

AW: Focus-Problem bei Firemonkey
 
Zur Not kannst du nen Timer draufsetzen, der auf 1 Millisekunde gestellt ist, und dann direkt den Fokus zurücksetzt. Schön ist das aber nicht.

Ich habe schon probiert TThread.Queue zu benutzen, aber das ging auch nicht.

himitsu 16. Aug 2012 11:57

AW: Focus-Problem bei Firemonkey
 
Timer, TThread.Queue oder eine Message sollte doch eigentlich klappen, da das so ist, als würde der Benutzer es (etwas später) selber machen :gruebel:
(Timer = überdimensionierte Message)

Wenn da intern nicht ebenfalls was zeitverzögert ausgelöst wird, dann könnte es schon passieren, daß dieses nach unserem Timer/Querue/Message erst zuschlägt.

jaenicke 16. Aug 2012 12:12

AW: Focus-Problem bei Firemonkey
 
Intern wird das einfach direkt zugewiesen, da passiert nichts hinterher. (Von den Animationen vielleicht mal abgesehen, keine Ahnung, aber die entscheidende Zuweisung ist da schon durch.)

himitsu 17. Aug 2012 22:11

AW: Focus-Problem bei Firemonkey
 
So, mal genauer nachgesehn.

OnExit müßte eigentlich OnBeforeExit heißen, denn u diesem Zeitpunkt liegt der Eingabefokus immernoch beim Control.
Control.SetFocus prüft, ob es nicht schon den Focus besitzt und macht dann nichts, womit im OnExit das SetFocus nie etwas macht, wenn man dieses auf das Control vom OnExit bezieht.

Delphi-Quellcode:
procedure TForm10.Edit1Exit(Sender: TObject);
begin
  if Edit1.Text = '' then begin
    Edit1.OnExit := nil; // Focused würde sonst eine Endlosschleife erstellen, da es wiederum OnExit aufruft
    Focused := nil;
    Edit1.OnExit := Edit1Exit;
    Edit1.SetFocus; // der Focus ist nun wo anders (nirgends, bzw. bei der Form selber), also funktioniert es nun
    Abort; // restliche FMX-Codes, zum Verlassen des Controls, abbrechen
  end;
end;
Aber um nochmal auf das angesprochene "OnBeforeExit" zu kommen.....
Delphi-Quellcode:
procedure TForm10.Edit1Exit(Sender: TObject);
begin
  if Edit1.Text = '' then
    Abort;
end;
So geht es auch, allerdings mit einem kleinen Fehler, denn laut FMX ist der Focus beim Control und auch bei eingabe eines Textes liegt der Fokus wirklich noch dort, aber Edit1.IsFocused sagt False, da es kurz vorm OnExit auf False gesetzt wurde, womit das Edit selber was anderes über sich denkt. :angle2:

Aber man kann dem Edit schnell wieder ordentlich Bescheid geben.
Delphi-Quellcode:
procedure TForm10.Edit1Exit(Sender: TObject);
begin
  if Edit1.Text = '' then begin
    (Edit1 as IControl).DoEnter;
    Abort;
  end;
end;
[add]
Letzteres hab ich dort http://www.delphipraxis.net/169747-b...ml#post1178667 mit integriert, inklusive einer Fehlermeldung. (siehe unten links in der Demo)

eddie11 20. Aug 2012 06:27

AW: Focus-Problem bei Firemonkey
 
wow, das gefällt mir gut!

ich werde sehen, wie ich das in mein Projekt einbauen kann.

@himitsu: vielen Dank

alledings wird auch hier ein Memoryleak erzeugt.

Darüber hinaus habe ich natürlich ein weiteres Problem: ein Abbruch-Button. Ich muss die Überprüfung abschalten können, damit der benutzer das Formular verlassen kann, ohne irgendeine Eingab zu machen. Ich glaube es wird wirklich das beste sein, die Validierung der Eingabe nicht im OnExit des Controls zu machen, sondern tatsächlich im OnEnter des nächsten Controls. Da ich grundsätzlich eigene Komponenten benutze (i.d.R. von der Originalcomponente abgeleitet) habe ich damit kein Problem. Beim OnEnter in ein Control merke ich mir das Control, beim OnEnter in das nächste Control führe ich die Validierung des ersten Controls aus. Wenn Ok, dann wenn weiter, wenn nicht, dann Focus setzen. Mal sehen wie weit ich damit komme.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:28 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