Jump to content
Sign in to follow this  
Magno

Weird behaviour when paint on PaintBox with Android

Recommended Posts

What I have: a frame with a semi-arc that represents a gauge for information like temperature. See the attached image. Each of these controls are into a frame which I create in runtime depending from what I receive from my server. 

The structure is: TFrame->TRectangle->TPaintBox. 

The issue: when I run with Windows the arcs are correctly drawn, I sent the Value so it draws fine the correct gauge. When I run with Android, using the example attached with 3 gauges, all the 3 gauges will get redraw with the same value, even I am pointing to only one. 

I am using a code I found a modified later, but most of it is close to the original, it will use anti-aliasing to draw the arc, the code is bellow:

type
   TAAArcSettings = record
      AStart, AEnd, Opacity: single;
      AThickStart, AThinkEnd: integer;
      Color: TAlphaColor;
   end;

procedure TframeGauge.DrawArcAA(AParams: TAAArcSettings);
var
   path: TPathData;
   poly: TPolygon;
begin

   path := TPathData.Create;
   path.AddArc(rect.CenterPoint, TPointF.Create(rw, rh), AParams.AStart, AParams.AEnd);
   path.AddArc(rect.CenterPoint(), TPointF.Create(rw - AParams.AThickStart, rh - AParams.AThinkEnd), AParams.AStart + AParams.AEnd,
     -AParams.AEnd);
   path.ClosePath();
   path.FlattenToPolygon(poly);

   APaintBox.Canvas.Fill.DefaultColor := TAlphaColorRec.Blue;
   APaintBox.Canvas.Stroke.Kind := TBrushKind.Solid;
   APaintBox.Canvas.Fill.Color := AParams.Color;
   APaintBox.Canvas.FillPolygon(poly, AParams.Opacity);

   path.DisposeOf;

end;

 

I make some calculations to define the initial and final angle plus the percent for the value representation. To intent set a value the code below is used:

 

   ArcSetting.AEnd := AEndAngle;
   ArcSetting.AStart := START_ANGLE;
   Rectangle1.BeginUpdate;
   APaintBox.Canvas.BeginScene;
   APaintBox.Repaint; // this will trigger the PaintBoxPaint() method and there inside I can the DrawArcAAA()
   APaintBox.Canvas.EndScene; 
   Rectangle1.EndUpdate;


There is a procedure TframeGauge.setGaugeValue(Value: integer) which will make the code above. In the main form it detects the frame and will call this procedure, but as I say all of any gauges will be drawn with the new value. This won't happen with Windows (both 32 and 64 bit).

 

Maybe FMX for Android it is required something else beyond I know 😞

 

Thanks for reading and any clue where I could search for?

 

Anotação 2020-06-13 230221.jpg

  • Like 2

Share this post


Link to post

Sorry, i don't have an answer to your problem, but i can't help myself with commenting on that screenshot, that is beautiful !

 

Is it your doing ?

If yes then "excellent work mate!"

Share this post


Link to post

I'm not very well experienced on FM, but possibly you're passing settings by value ! those could be a very hard source of bug to detect !

procedure TframeGauge.DrawArcAA(AParams: TAAArcSettings);

 

Share this post


Link to post
6 hours ago, Kas Ob. said:

Sorry, i don't have an answer to your problem, but i can't help myself with commenting on that screenshot, that is beautiful !

 

Is it your doing ?

If yes then "excellent work mate!"

Yes it is, thank you. I thinking to release it all source code later. The idea behind is simple and it is a quarantine project: I was thinking to monitor some of my computer sensors using WMI queries, but quickly I realise the information about GPU is device dependent on drivers and the time I would expend to accomplish won't be wort. I found a software called Open Hardware Monitor (https://github.com/openhardwaremonitor/openhardwaremonitor) that you can keep it running in background and expands the WMI. Now I have a server that read temps and loads so I can choose what I want to monitor. My computer case has a glass so I could put an old tablet or phone there inside 😄 

 

Here's more decent screenshot of both client and server (still a WIP).

 

Screenshot.jpg

  • Like 2

Share this post


Link to post
1 hour ago, Mahdi Safsafi said:

I'm not very well experienced on FM, but possibly you're passing settings by value ! those could be a very hard source of bug to detect !


procedure TframeGauge.DrawArcAA(AParams: TAAArcSettings);

 

I will try move it, thanks but as they are different frames so one should not touch the other...

Share this post


Link to post
1 hour ago, Magno said:

I will try move it, thanks but as they are different frames so one should not touch the other...

I think Mahdi here was asking about if you are sure in passing AParams by value, meaning AParams is been copied every time to the stack before been passed to DrawArcAA, there is no point in that function to be used like that, also this is slow and may be somehow causing the problem, try changing the DrawArcAA declaration to :

procedure TframeGauge.DrawArcAA(const AParams: TAAArcSettings);
//  or 
procedure TframeGauge.DrawArcAA(var AParams: TAAArcSettings);

 

Share this post


Link to post
23 hours ago, Kas Ob. said:

I think Mahdi here was asking about if you are sure in passing AParams by value, meaning AParams is been copied every time to the stack before been passed to DrawArcAA, there is no point in that function to be used like that, also this is slow and may be somehow causing the problem, try changing the DrawArcAA declaration to :


procedure TframeGauge.DrawArcAA(const AParams: TAAArcSettings);
//  or 
procedure TframeGauge.DrawArcAA(var AParams: TAAArcSettings);

 

There was no change on FMX. Maybe if I move to object component I could have more success but for this project I dunno...

Share this post


Link to post
1 hour ago, Magno said:

There was no change on FMX. Maybe if I move to object component I could have more success but for this project I dunno...

OK , you lost me here as i don't understand to what FMX change you are referring to, and i think you didn't understand what was the suggestion to try.

 

to try :

Don't change anything except than the declaration of DrawArcAA , make it like this

procedure TframeGauge.DrawArcAA(const AParams: TAAArcSettings);

 

 

Now let me explain what is the difference between these cases 

1) default (no const or var case)

  Params.AStart := 5;
  DrawArcAA(Params);
  // Params.AStart value is still  5

procedure TTframeGauge.DrawArcAA(AParams: TAAArcSettings);
..
begin
  ..
  AParams.AStart := 6;          // will compile but this new value will only be from ths point forward inside this function only
  ..
end;

2) var case

begin
  Params.AStart := 5;
  DrawArcAA(Params);
  // Params.AStart value is now 6
end;

procedure TTframeGauge.DrawArcAA(var AParams: TAAArcSettings);
..
begin
  ..
  AParams.AStart := 6;          // will compile but this new value will be here and will changed in AParams forever
  ..
end;

3) const 

begin
  Params.AStart := 5;
  DrawArcAA(Params);
end;

procedure TTframeGauge.DrawArcAA(const AParams: TAAArcSettings);
..
begin
  ..
  AParams.AStart := 6;          // error ! will not compile as the AParams will considered and handled as constant by the compiler 
  ..
end;

Your are better with const in that function because you are not changing any of its fields, consts and var are slightly faster than the default ( without const or var ) 

Share this post


Link to post
On 6/15/2020 at 2:12 PM, Kas Ob. said:

OK , you lost me here as i don't understand to what FMX change you are referring to, and i think you didn't understand what was the suggestion to try.

 

to try :

Don't change anything except than the declaration of DrawArcAA , make it like this


procedure TframeGauge.DrawArcAA(const AParams: TAAArcSettings);

3) const 


begin
  Params.AStart := 5;
  DrawArcAA(Params);
end;

procedure TTframeGauge.DrawArcAA(const AParams: TAAArcSettings);
..
begin
  ..
  AParams.AStart := 6;          // error ! will not compile as the AParams will considered and handled as constant by the compiler 
  ..
end;

Your are better with const in that function because you are not changing any of its fields, consts and var are slightly faster than the default ( without const or var ) 

Yes, I understand that. Well, using const did not solved. 

 

Well, as I said, with Windows it works correctly. With Android once I draw it will replicate the value to any other gauge there. I think it somehow related to the painting method, I really dunno yet.

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×