Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2014-09

TAChart with transparent background

7 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Roberto P.

Dear List,

is it possible to have a chart with transparent background, so that a picture behind the plot is visible?

From the wiki I understand that TAChart does not support BackImage property

as in Delphi, which would fit the purpouse.
However I read thay using BGRAbitmap as a back-end it is possible to use transparency. I managed to install the required packages and activate the back-end, but I did not understand from the tutorial ( http://wiki.freepascal.org/BGRABitmap_tutorial_TAChart) how to go on.

Does anyone has an example?

Thanks a lot,

R#
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20140902/d24e80b5/attachment.html>

Reply by email

Werner Pamler

It is not fully clear to me what you mean by "a chart with transparent background". Do you want to see the form underneath the chart? I fear this is not easily possible. Or do you want to have a background image in the chart? For the latter case this code is working fine with me:

type
   TForm1 = class(TForm)
     Chart1: TChart;
     procedure Chart1BeforeDrawBackground(ASender: TChart; ACanvas: TCanvas;
       const ARect: TRect; var ADoDefaultDrawing: Boolean);
     procedure Chart1BeforeDrawBackWall(ASender: TChart; ACanvas: TCanvas;
       const ARect: TRect; var ADoDefaultDrawing: Boolean);
     procedure FormCreate(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
   private
     { private declarations }
     FBackImage: TPicture;
   public
     { public declarations }
   end;
....
procedure TForm1.Chart1BeforeDrawBackWall(ASender: TChart; ACanvas: TCanvas;
   const ARect: TRect; var ADoDefaultDrawing: Boolean);
begin
   ADoDefaultDrawing := false;
   ACanvas.StretchDraw(ARect, FBackImage.Graphic);
end;
procedure TForm1.Chart1BeforeDrawBackground(ASender: TChart; ACanvas:
TCanvas;
   const ARect: TRect; var ADoDefaultDrawing: Boolean);
begin
   ACanvas.GradientFill(ARect, clSkyBlue, clWhite, gdVertical);
   ADoDefaultDrawing := false;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
   FBackImage := TPicture.Create;
   FBackImage.LoadFromFile('C:\lazarus-svn\images\splash_logo.png');
   // please adapt this path to your lazarus installation
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
   FBackImage.Free;
end;

The basic idea is to assign a handler to the chart events OnBeforeDrawBackWall or OnBeforeDrawBackground and disable the default background painting by setting ADoDefaultDrawing to false. The first event replaces painting of the area enclosed by the chart's frame ("Back wall"), the other one replaces painting of the entire chart background. Above example paints the Lazarus splash-logo as BackWall and a gradient as background.

Maybe I'll once write a tutorial on this topic...

Reply by email

Roberto P.
to Werner Pamler

Thank you very much.
I need a background image, therefore as soon as I am back at the office I'll try your code.
Thank you again!

R#

2014-09-02 18:18 GMT+02:00 Werner Pamler :

Show quoted text 67 lines
It is not fully clear to me what you mean by "a chart with transparent background". Do you want to see the form underneath the chart? I fear this is not easily possible. Or do you want to have a background image in the chart? For the latter case this code is working fine with me: type TForm1 = class(TForm) Chart1: TChart; procedure Chart1BeforeDrawBackground(ASender: TChart; ACanvas: TCanvas; const ARect: TRect; var ADoDefaultDrawing: Boolean); procedure Chart1BeforeDrawBackWall(ASender: TChart; ACanvas: TCanvas; const ARect: TRect; var ADoDefaultDrawing: Boolean); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { private declarations } FBackImage: TPicture; public { public declarations } end; .... procedure TForm1.Chart1BeforeDrawBackWall(ASender: TChart; ACanvas: TCanvas; const ARect: TRect; var ADoDefaultDrawing: Boolean); begin ADoDefaultDrawing := false; ACanvas.StretchDraw(ARect, FBackImage.Graphic); end; procedure TForm1.Chart1BeforeDrawBackground(ASender: TChart; ACanvas: TCanvas; const ARect: TRect; var ADoDefaultDrawing: Boolean); begin ACanvas.GradientFill(ARect, clSkyBlue, clWhite, gdVertical); ADoDefaultDrawing := false; end; procedure TForm1.FormCreate(Sender: TObject); begin FBackImage := TPicture.Create; FBackImage.LoadFromFile('C:\lazarus-svn\images\splash_logo.png'); // please adapt this path to your lazarus installation end; procedure TForm1.FormDestroy(Sender: TObject); begin FBackImage.Free; end; The basic idea is to assign a handler to the chart events OnBeforeDrawBackWall or OnBeforeDrawBackground and disable the default background painting by setting ADoDefaultDrawing to false. The first event replaces painting of the area enclosed by the chart's frame ("Back wall"), the other one replaces painting of the entire chart background. Above example paints the Lazarus splash-logo as BackWall and a gradient as background. Maybe I'll once write a tutorial on this topic... -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20140904/5a09708d/attachment.html>

Reply by email

Roberto P.
to Roberto P.

Though really late, I can confirm that the solution is working fine. I still have to add some profiling code to measure it, though with added background it seems perceivably slower even on a recent PC (core i5 vpro). Are BGRA or other backends known to be faster?

thanks anyway for the help!

R#

2014-09-04 1:08 GMT+02:00 Roberto P. :

Show quoted text 79 lines
Thank you very much. I need a background image, therefore as soon as I am back at the office I'll try your code. Thank you again! R# 2014-09-02 18:18 GMT+02:00 Werner Pamler : > It is not fully clear to me what you mean by "a chart with transparent > background". Do you want to see the form underneath the chart? I fear this > is not easily possible. Or do you want to have a background image in the > chart? For the latter case this code is working fine with me: > > type > TForm1 = class(TForm) > Chart1: TChart; > procedure Chart1BeforeDrawBackground(ASender: TChart; ACanvas: > TCanvas; > const ARect: TRect; var ADoDefaultDrawing: Boolean); > procedure Chart1BeforeDrawBackWall(ASender: TChart; ACanvas: TCanvas; > const ARect: TRect; var ADoDefaultDrawing: Boolean); > procedure FormCreate(Sender: TObject); > procedure FormDestroy(Sender: TObject); > private > { private declarations } > FBackImage: TPicture; > public > { public declarations } > end; > .... > procedure TForm1.Chart1BeforeDrawBackWall(ASender: TChart; ACanvas: > TCanvas; > const ARect: TRect; var ADoDefaultDrawing: Boolean); > begin > ADoDefaultDrawing := false; > ACanvas.StretchDraw(ARect, FBackImage.Graphic); > end; > > procedure TForm1.Chart1BeforeDrawBackground(ASender: TChart; ACanvas: > TCanvas; > const ARect: TRect; var ADoDefaultDrawing: Boolean); > begin > ACanvas.GradientFill(ARect, clSkyBlue, clWhite, gdVertical); > ADoDefaultDrawing := false; > end; > > procedure TForm1.FormCreate(Sender: TObject); > begin > FBackImage := TPicture.Create; > FBackImage.LoadFromFile('C:\lazarus-svn\images\splash_logo.png'); > // please adapt this path to your lazarus installation > end; > > procedure TForm1.FormDestroy(Sender: TObject); > begin > FBackImage.Free; > end; > > The basic idea is to assign a handler to the chart events > OnBeforeDrawBackWall or OnBeforeDrawBackground and disable the default > background painting by setting ADoDefaultDrawing to false. The first event > replaces painting of the area enclosed by the chart's frame ("Back wall"), > the other one replaces painting of the entire chart background. Above > example paints the Lazarus splash-logo as BackWall and a gradient as > background. > > Maybe I'll once write a tutorial on this topic... > > > -- > _______________________________________________ > Lazarus mailing list > > http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus >

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20140915/5932c91a/attachment-0001.html>

Reply by email

Werner Pamler

I added some simple time measuring code (using GetTickCount) to the background image tutorial to see the speed loss that you mention: Without the backgrounds (Lazarus logo and gradient) the GetTickCount reports 0 ms between the OnBeforeDrawBackground and OnAfterPaint events, while with the backgrounds it reports 16 ms, sometimes 0 ms. Replacing the StretchDraw by a simple Draw in the painting of the logo, brings down the time also to 0. Therefore I'd guess that the background painting is not perceivable unless you squeeze a 20 mega-pixel photo into the chart area or load the image during the painting event.

What exactly are you doing?

Reply by email

Roberto P.
to Werner Pamler

The image is a 30KB png, not much.
It is smaller than the area, so it gets actually stretched. Can I use Draw instead of StretchDraw if I make the image exactly the size I need?
I can force the form size.

I think that tens of milliseconds can be actually relevant, because I am plotting data received (and processed) every 50ms from a serial port.

R#

2014-09-16 0:07 GMT+02:00 Werner Pamler :

Show quoted text 19 lines
I added some simple time measuring code (using GetTickCount) to the background image tutorial to see the speed loss that you mention: Without the backgrounds (Lazarus logo and gradient) the GetTickCount reports 0 ms between the OnBeforeDrawBackground and OnAfterPaint events, while with the backgrounds it reports 16 ms, sometimes 0 ms. Replacing the StretchDraw by a simple Draw in the painting of the logo, brings down the time also to 0. Therefore I'd guess that the background painting is not perceivable unless you squeeze a 20 mega-pixel photo into the chart area or load the image during the painting event. What exactly are you doing? -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20140916/1dc8f69d/attachment.html>

Reply by email

Werner Pamler

I see. If you can keep the chart size unchanged then it is certainly a good idea to stretch the image to the requested size immediately after loading and use a simple "Draw" of the obtained image while charting. If you know the range of your data in advance it may also help to freeze the chart extent to avoid unnecessary repaints when data arrive. And you could also enclose the AddXY calls by calls to Begin/EndUpdate of the ChartSource. Avoiding unnecessary repainting can have a dramatic effect on speed.

Reply by email