Eventloop?!?

Forum für alles rund um die MSEide und MSEgui
Antworten
Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Eventloop?!?

Beitrag von fliegermichl »

Ich habe hier irgendwie einen zirkulären Eventloop gebastelt und weiss nicht so recht, wie ich das lösen kann?
Das Programm funktioniert aber ruft das Paintbox.onPaint irgendwie zirkulär auf. (Der Debugserver bekommt in einer Tour "Painiting" obwohl die Maus gar nicht bewegt wird. Danz ganze pausiert erst dann, wenn man die Maus aus der Paintbox rausschiebt. Ich muss aber auf die Bewegung der Maus mit neuzeichnen der Paintbox reagieren.

Code: Alles auswählen

 
unit main;
{$ifdef FPC}{$mode objfpc}{$h+}{$endif}
interface
uses
 msetypes,mseglob,mseguiglob,mseguiintf,mseapplication,msestat,msemenus,msegui,
 msegraphics,msegraphutils,mseevent,mseclasses,msewidgets,mseforms,msedock,
 msedockpanelform,msesimplewidgets, dbugintf;
 
type
 tmymousehandler = class
 private
  startx, starty,
  fx, fy : integer;
  fdown : boolean;
 public
  procedure mymousemove(sender : twidget; var ainfo : mouseeventinfoty);
  procedure mymousedown(sender : tobject; var ainfo : mouseeventinfoty);
  procedure mymouseup(sender : tobject; var ainfo : mouseeventinfoty);
  procedure mymousehandler(const sender : twidget; var ainfo : mouseeventinfoty);
  procedure mypaint(sender : tobject; Canvas : TCanvas);
 end;
 
 tmainfo = class(tdockpanelform)
   pb: tpaintbox;
   procedure formcreate(const sender: TObject);
   procedure pbpaint(const sender: twidget; const acanvas: tcanvas);
 private
  fHandler : tmymousehandler;
 end;
var
 mainfo: tmainfo;
implementation
uses
 main_mfm;
{ tmymousehandler }
 
procedure tmymousehandler.mymousemove(sender: twidget;
               var ainfo: mouseeventinfoty);
begin
 fx := ainfo.pos.x;
 fy := ainfo.pos.y;
 sender.invalidate;
end;
 
procedure tmymousehandler.mymousedown(sender: tobject;
               var ainfo: mouseeventinfoty);
begin
 fdown := true;
 startx := ainfo.pos.x;
 starty := ainfo.pos.y;
end;
 
procedure tmymousehandler.mymouseup(sender: tobject;
               var ainfo: mouseeventinfoty);
begin
 fdown := false;
end;
 
procedure tmymousehandler.mymousehandler(const sender: twidget;
               var ainfo: mouseeventinfoty);
begin
 case ainfo.eventkind of
  ek_mousemove : mymousemove(sender, ainfo);
  ek_buttonpress : mymousedown(sender, ainfo);
  ek_buttonrelease : mymouseup(sender, ainfo);
 end;
end;
 
 
 
procedure tmymousehandler.mypaint(sender: tobject; Canvas: TCanvas);
begin
 SendDebug('painting');
 if fdown then
 begin
  canvas.color := cl_black;
  canvas.drawline(mp(startx, starty), mp(fx, fy));
 end;
end;
 
procedure tmainfo.formcreate(const sender: TObject);
begin
 fHandler := TMyMouseHandler.Create;
 pb.onmouseevent := @fhandler.mymousehandler;
 
end;
 
procedure tmainfo.pbpaint(const sender: twidget; const acanvas: tcanvas);
begin
 fhandler.mypaint(sender, acanvas);
end;
 
end.
 

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: Eventloop?!?

Beitrag von mse »

fliegermichl hat geschrieben:Ich habe hier irgendwie einen zirkulären Eventloop gebastelt und weiss nicht so recht, wie ich das lösen kann?

Kann ich nicht nachvollziehen. Allerdings habe ich debugwriteln() aus msesysutils verwendet:

Code: Alles auswählen

 
procedure tmymousehandler.mypaint(sender: tobject; Canvas: TCanvas);
begin
//SendDebug('painting');
 inc(fcount);
 debugwriteln(inttostr(fcount)+' painting');
 if fdown then
 begin
  canvas.color := cl_black;
  canvas.drawline(mp(startx, starty), mp(fx, fy));
 end;
end;
 

MSEgui hat TObjectPicker um solche Aufgaben zu lösen, ein Anwendungsbeispiel ist TXYChartEdit aus tab widget.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Eventloop?!?

Beitrag von fliegermichl »

Das ist interessant. Mit debugwriteln geht es bei mir auch.

Wie dem auch sei. so habe ich wenigstens einen Weg meine Anwendung zu debuggen. Solche Sachen sind ohnehin immer schwierig zu debuggen wo der Debugger das Verhalten der Anwendung beeinflusst.

AndreasMR
Beiträge: 98
Registriert: Di 4. Aug 2015, 15:29
OS, Lazarus, FPC: Linux, Raspbian, Windows
CPU-Target: 64/32 Bit

Re: Eventloop?!?

Beitrag von AndreasMR »

Hallo Fliegermichl,


fliegermichl hat geschrieben:Ich habe hier irgendwie einen zirkulären Eventloop gebastelt und weiss nicht so recht, wie ich das lösen kann?
Ich muss aber auf die Bewegung der Maus mit neuzeichnen der Paintbox reagieren.


Was lässt Dich glauben, dass Du das musst?

Neuzeichnen musst Du doch erst, wenn irgendein Ereignis passiert ist, irgendwas angeklickt oder losgelassen wurde. Wenn Du bei jedem Pixel, den sich die Maus bewegt, irgendwas (Größeres) neuzeichnest, dann hieße das bei Bewegung 50 Pixel schräg bewegt bereits 100 x Neuzeichnen. Das schafft keine noch so gute Routine.

Suche Dir ein anderes Ereignis, das das Neuzeichnen auslösen sollst - und Dein Programm wird rasend schnell werden.

Das ist z.B. auch der Grund, weshalb bei "Sizing"-Ereignissen ein Filter gesetzt wird. Erst wenn die Maus zum Stillstand gekommen ist, wird die Größenänderung eines Fensters vorgenommen (alte Größe auf neue Größe) - und nicht bei jeder einzelnen temporären Größenänderung. Solange die Maus nicht losgelassen wurde, gilt ein Ereignis als nicht abgeschlossen, um ein Ereignis auslösen zu dürfen.


Beste Grüße

Andreas
Ubuntu 14.04 LTS / Raspbian / Windows: Lazarus ab 0.9 bis 3.0

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: Eventloop?!?

Beitrag von mse »

MSEgui überspringt aufgelaufene mousemove events und verarbeitet lediglich den letzten. Zu dem wird update() erst aufgerufen wenn die event queue leer ist. Von daher ist das invalidisieren des widgets in onmouseevent schon möglich. Ich empfehle trotzdem die beweglichen Elemente mit canvas.rasterop rop_xor zu zeichnen und nicht das widget zu invalidisieren welches dann komplett neu gezeichnet werden muss. TObjectPicker bietet die Infrastruktur dazu.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Eventloop?!?

Beitrag von fliegermichl »

AndreasMR hat geschrieben:Hallo Fliegermichl,


fliegermichl hat geschrieben:Ich habe hier irgendwie einen zirkulären Eventloop gebastelt und weiss nicht so recht, wie ich das lösen kann?
Ich muss aber auf die Bewegung der Maus mit neuzeichnen der Paintbox reagieren.


Was lässt Dich glauben, dass Du das musst?

Neuzeichnen musst Du doch erst, wenn irgendein Ereignis passiert ist, irgendwas angeklickt oder losgelassen wurde. Wenn Du bei jedem Pixel, den sich die Maus bewegt, irgendwas (Größeres) neuzeichnest, dann hieße das bei Bewegung 50 Pixel schräg bewegt bereits 100 x Neuzeichnen. Das schafft keine noch so gute Routine.

Suche Dir ein anderes Ereignis, das das Neuzeichnen auslösen sollst - und Dein Programm wird rasend schnell werden.

Das ist z.B. auch der Grund, weshalb bei "Sizing"-Ereignissen ein Filter gesetzt wird. Erst wenn die Maus zum Stillstand gekommen ist, wird die Größenänderung eines Fensters vorgenommen (alte Größe auf neue Größe) - und nicht bei jeder einzelnen temporären Größenänderung. Solange die Maus nicht losgelassen wurde, gilt ein Ereignis als nicht abgeschlossen, um ein Ereignis auslösen zu dürfen.


Beste Grüße

Andreas


Wenn der Anwender in dem CAD Programm ein Gebäude mit der Maus verschiebt, muss ich ihm schon anzeigen wo er es gerade hingeschoben hat :-)

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Eventloop?!?

Beitrag von Socke »

fliegermichl hat geschrieben:Wenn der Anwender in dem CAD Programm ein Gebäude mit der Maus verschiebt, muss ich ihm schon anzeigen wo er es gerade hingeschoben hat :-)

Wenn das Bild mit einer definierten Frequenz (z.B. 60 Hz oder 120 Hz) aktualisiert wird, sollte das hoffentlich ausreichen.
Beim Mausverschieben speicherst du also nur die neue Mausposition und kannst dann in einem Timer-Event oder sogar separaten Thread das neue Bild berechnen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Eventloop?!?

Beitrag von fliegermichl »

mse hat geschrieben:MSEgui überspringt aufgelaufene mousemove events und verarbeitet lediglich den letzten. Zu dem wird update() erst aufgerufen wenn die event queue leer ist. Von daher ist das invalidisieren des widgets in onmouseevent schon möglich. Ich empfehle trotzdem die beweglichen Elemente mit canvas.rasterop rop_xor zu zeichnen und nicht das widget zu invalidisieren welches dann komplett neu gezeichnet werden muss. TObjectPicker bietet die Infrastruktur dazu.


Das erklärt auch, weshalb meine eigene Erkennung von aufgelaufenen MouseEvents nicht gegriffen hat :-)

Übrigens, dass ich dich hier in letzter Zeit mit Fragen bombardiert habe, mag den Eindruck erwecken, daß ich nicht mit mseGUI zufrieden bin. Dem ist mitnichten so. Ich halte es für ein ganz tolles ausgereiftes und wahnsinnig schnelles System. Ausserdem die fehlenden Abhängigkeiten zu irgendwelchen WidgetSets macht es unglaublich viel besser nachvollziehbar.

auch solcher Mist wie bei Lazarus "External Exception segfault" mit einem so aussagelosem Stacktrace der nur Fragezeichen beinhaltet ist mir hier noch nie passiert.

Einzig die Dokumentation ist etwas dürftig.

Antworten