AGB  ·  Datenschutz  ·  Impressum  







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

FireMonkey Sammelthread

Ein Thema von mquadrat · begonnen am 1. Sep 2011 · letzter Beitrag vom 27. Jul 2013
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: FireMonkey Sammelthread

  Alt 9. Jan 2013, 23:41
Ich habe noch ein wenig probiert und noch ein paar Punkte herausbekommen - aber keine Lösung gefunden.

Wenn ich aus meinem Framework heraus ein Control neu zeichnen lasse wird bis zum Formular hoch das entsprechende Rect als ungültig deklariert.
Allerdings erreiche ich eine wirkliche Neuzeichnung des Formulars erst durch eine Größenänderung des Formulars.

Im Formular reicht ein Timer, der ein Invalidate ausführt.
Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Invalidate;
end;

In meinem Framework ermittle ich das korrekte Form, kann aber kein Neuzeichnen veranlassen.
Mit EndUpdate und ReCreate klappt das aber das Formular wird kurz ausgeblendet und neu gezeichnet.
Delphi-Quellcode:
procedure TssfCtrl.RefreshControl(Control: TControl);
var
  P: TFmxObject;
begin
  if not Assigned(Control) then
    Exit;
  // Control.BeginUpdate;
  // Control.Repaint;
  // Control.EndUpdate;
  // Exit;
  P := Control.Parent;
  while Assigned(P.Parent) do
    P := P.Parent;
  if (P is TForm) then
  begin
    // public Methoden:
    // (P as TForm).Invalidate; // nix
    //
    // (P as TForm).BeginUpdate;
    // (P as TForm).EndUpdate; // flackert
    //
    // protected Methoden:
    // TCrackForm(P).Realign; // nix
    // TCrackForm(P).Resize; // nix
    // TCrackForm(P).Recreate; // flackert
    // TCrackForm(P).Updating; // nix
    // TCrackForm(P).Updated; // nix
    // TCrackForm(P).UpdateStyle; // nix
    // TCrackForm(P).ResizeHandle; // nix
  end;
end;
Das Zeichnen meines eigentlichen Controls kann ich an der Stelle sogar weg lassen (wird schon durch die Eigenschaftsänderung veranlasst).

Offenbar kriegt der Mainthread wohl irgendwie von der Änderung nichts mit (obwohl ich gar nicht wirklich sagen kann in welchem Prozess die Änderung gezeichnet wird).
In dem Zusammenhang stellt sich natürlich auch noch die Frage, wie das mit dem Repaint dann unter Mac bzw. auf den mobilen Plattformen laufen würde.

Falls jemand mit meinem Baustellenprojekt (XE3) mal herumspielen will könnte ich das mal per Mail schicken.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: FireMonkey Sammelthread

  Alt 13. Jan 2013, 00:22
Hmm, ich komme an der Stelle nicht wirklich weiter. Sehr rätselhaft...

Also ich bastle ein Databinding-Framework (mal sehen, was draus wird, erst mal ist es auf jeden Fall interessant).
Wenn ich aus einem Edit eine Änderung an die Datenschicht schicke wird die GUI danach über die Änderung informiert und die GUI-Controls werden veranlasst, sich mit den neuen Daten zu zeichnen.

Das funktioniert auch - nur wird die Änderung nicht sichtbar bis ich die Formulargrößere ändere oder z.B. in einem Timer Invalidate für das Formular ausführe.
Der richtige Wert liegt aber dann "nachweislich" ja in den Controls schon vor.

Das komische: Wenn ich aus einem Timer heraus z.B. TimeToStr(Now) in die Datenschicht schicke (anstatt bei einer Texteingabe im Edit) werden die an das Feld gebundenen Controls immer korrekt gezeichnet (bzw. der entsprechende Bereich auf dem Formular). Die anderen Controls aber wiederum nicht.

Wenn bei überschneidenen Controls das andere Control neu gezeichnet wird (z.B. wenn ein Edit focusiert wird), sieht man von dem nicht aktualisierten Control einige Pixel, die jetzt aktualisiert wurden.
Also wurde die Änderung auf dem Screen noch nicht aktualisiert, im Puffer sind die aber schon vorhanden.

Wenn jemand sich in dem Bereich mal beschäftigt, dann wäre ich für einen Tipp dankbar.
(Kann auch gern den aktuellen Stand schicken.)
Angehängte Grafiken
Dateityp: jpg fmr.jpg (75,5 KB, 24x aufgerufen)
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  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
 
#3

AW: FireMonkey Sammelthread

  Alt 13. Jan 2013, 01:43
Ich habe zwar nicht dieses aber ein Verhalten beobachtet, was wohl die gleiche Ursache hat.

Beim TGrid wollte ich eine Spalte immer so breit machen, dass die gesamte Gridbreite ausgefüllt ist.
Eigentlich ganz einfach: Kleine procedure und im Resize Event des TGrid diese aufrufen.

Aber denkste, das funktioniert nicht immer (eher öfter nicht), allerdings wird das Ereignis zuverlässig aufgerufen jedoch teilweise bevor die Änderungen wirklich stattgefunden haben.

Seltsam, ist aber so ...

Meine Lösung dafür heisst nun, dass ich im Resize Event einen IdleEvent auslöse und der wird erst dann ausgeführt, wenn die Anwendung in den Idle Zustand geht - analog zum TApplicationEvent.OnIdle, nur wird mein Event nur einmal ausgelöst.
Und schon funktioniert es zuverlässig.
(Eigentlich ist das schon fast Holzhammer, aber wer hilft hat erst mal recht )
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
Unx

Registriert seit: 24. Aug 2010
30 Beiträge
 
#4

AW: FireMonkey Sammelthread

  Alt 13. Jan 2013, 02:52
(Eigentlich ist das schon fast Holzhammer, aber wer hilft hat erst mal recht )
Für mich hört sich das eher an..... was zu verwenden was man nicht verwenden sollte!
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: FireMonkey Sammelthread

  Alt 20. Jan 2013, 20:39
Ich arbeite an einigen FMX-Controls bzw. versuche das.

Irgendwie finde ich die FMX-Controls im Allgemeinen unnötig kompliziert aufgebaut.
Z.B. werden ín einem Header die Items in der Childrenliste gespeichert und dann anhand der Classe herausgesucht.
Das Hinzufügen von Einträgen funktioniert zwar, aber die Breite passt nicht immer und wird erst bei einer Größenänderung des Parent aktualisiert.
Dass AddObject neue Einträge vor dem automatischen ersten Eintrag "addiert" werden ist nicht dokumentiert.
Realign ist nicht öffentlich.

Von der oder anderer Sorte gibt es an allen Ecken Probleme bzw. (für mich) Unklarheiten.
Ohne jetzt Details ausdiskutieren zu wollen hätte ich mir das ganze Framework irgendwie übersichtlicher und klarer strukturiert erhofft.

Seht Ihr das auch so (insb. beim Arbeiten an eigenen Controls)?
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
greenmile

Registriert seit: 17. Apr 2003
1.107 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: FireMonkey Sammelthread

  Alt 21. Jan 2013, 07:55
Willkommen im Club
  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
 
#7

AW: FireMonkey Sammelthread

  Alt 23. Jan 2013, 13:51
(Eigentlich ist das schon fast Holzhammer, aber wer hilft hat erst mal recht )
Für mich hört sich das eher an..... was zu verwenden was man nicht verwenden sollte!
Hast ja recht, FireMonkey ist noch Beta und sollte daher in Produktivlösungen nicht verwendet werden ... manchmal kann man aber nicht anders und dann muss man die Bugs eben irgendwie wegbügeln
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
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: FireMonkey Sammelthread

  Alt 3. Feb 2013, 23:20
Hmm, ich komme an der Stelle nicht wirklich weiter. Sehr rätselhaft...

Also ich bastle ein Databinding-Framework (mal sehen, was draus wird, erst mal ist es auf jeden Fall interessant).
Wenn ich aus einem Edit eine Änderung an die Datenschicht schicke wird die GUI danach über die Änderung informiert und die GUI-Controls werden veranlasst, sich mit den neuen Daten zu zeichnen.

Das funktioniert auch - nur wird die Änderung nicht sichtbar bis ich die Formulargrößere ändere oder z.B. in einem Timer Invalidate für das Formular ausführe.
Der richtige Wert liegt aber dann "nachweislich" ja in den Controls schon vor.

Das komische: Wenn ich aus einem Timer heraus z.B. TimeToStr(Now) in die Datenschicht schicke (anstatt bei einer Texteingabe im Edit) werden die an das Feld gebundenen Controls immer korrekt gezeichnet (bzw. der entsprechende Bereich auf dem Formular). Die anderen Controls aber wiederum nicht.

Wenn bei überschneidenen Controls das andere Control neu gezeichnet wird (z.B. wenn ein Edit focusiert wird), sieht man von dem nicht aktualisierten Control einige Pixel, die jetzt aktualisiert wurden.
Also wurde die Änderung auf dem Screen noch nicht aktualisiert, im Puffer sind die aber schon vorhanden.

Wenn jemand sich in dem Bereich mal beschäftigt, dann wäre ich für einen Tipp dankbar.
(Kann auch gern den aktuellen Stand schicken.)
Das Zeichnen des Formulars muss syncronisiert werden.
Ich nutze dazu in meinem Framework jetzt einen Thread. Das funktioniert in den ersten Tests perfekt.
Delphi-Quellcode:
  TInvalidateThread = class(TThread)
  private
    fForm: TForm;
    procedure DoInvalidate;
  protected
    procedure Execute; override;
  public
    constructor Create(aForm: TForm);
  end;

...

{ TInvalidateThread }

constructor TInvalidateThread.Create(aForm: TForm);
begin
  fForm := aForm;
  FreeOnTerminate := True;
  inherited Create(False);
end;

procedure TInvalidateThread.DoInvalidate;
begin
  if Assigned(fForm) then
    fForm.Invalidate;
end;

procedure TInvalidateThread.Execute;
begin
  inherited;
  Synchronize(DoInvalidate);
end;
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  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
 
#9

AW: FireMonkey Sammelthread

  Alt 4. Feb 2013, 18:42
Das Zeichnen des Formulars muss syncronisiert werden.
Ich nutze dazu in meinem Framework jetzt einen Thread. Das funktioniert in den ersten Tests perfekt.
Das Formular muss keineswegs synchronisiert werden. Allerdings scheint es so, dass zum Zeitpunkt der Events noch nicht alles fertig berechnet ist oder Events verschluckt werden (warum auch immer, ist halt komisch).

Das das mit dem Thread funktioniert hat eine andere Ursache

Delphi-Referenz durchsuchenTThread.Synchronize wartet bis der MainThread im Idle Zustand ist. In den Idle Zustand geht der MainThread dann, wenn es für den nichts mehr zu tun gibt ... ausser auf Events/Messages zu warten. Erreichen kann man das auch mit einem Timer (der Thread ist da schon besser, aber mir geht es darum zu zeigen, dass es nichts mit Synchronisieren zu schaffen hat).

Hier mal eine ganz billige Demo mit einem TStringGrid (Align:=alClient ) und im OnResize Event lassen wir uns die ClientWidth ausgeben. (Das Panel ist nur als Container für die beiden Labels gedacht).

Dabei sieht man, dass der Wert beim EventAufruf dem endgültigen Wert (TimerEvent) hinterher hinkt.
Delphi-Quellcode:
unit Main_ViewU;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
  System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Grid,
  FMX.Layouts, FMX.ListBox;

type
  TForm1 = class( TForm )
    StringGrid1 : TStringGrid;
    Panel1 : TPanel;
    Label1 : TLabel;
    Label2 : TLabel;
    Timer1 : TTimer;
    procedure StringGrid1Resize( Sender : TObject );
    procedure Timer1Timer( Sender : TObject );
  private
  public
  end;

var
  Form1 : TForm1;

implementation

{$R *.fmx}

procedure TForm1.StringGrid1Resize( Sender : TObject );
begin
  Timer1.Enabled := False;
  Label1.Data := StringGrid1.ClientWidth;
  Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer( Sender : TObject );
begin
  Timer1.Enabled := False;
  Label2.Data := StringGrid1.ClientWidth;
end;

end.
Trotz dieser Erkenntnis ist dieses Verhalten in meinen Augen fehlerhaft ... evtl. sollte ich mal einen QC Eintrag verfassen (oder vorher danach suchen )
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
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: FireMonkey Sammelthread

  Alt 4. Feb 2013, 19:14
Ja stimmt, ich meinte auch zeitlich mit dem MainThread syncronisieren (nicht kritische Zugriffe)...
Mit dem Thread ist das schon etwas günstiger als mit dem Timer.

Wenn Du das in der QC vernünftig beschrieben kriegst, dann gebe ich Dir eine Milch mit Honig aus...
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 00:21 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz