Recent

Author Topic: Adding event to runtime-created series  (Read 5233 times)

bobby100

  • Full Member
  • ***
  • Posts: 100
    • Malzilla
Adding event to runtime-created series
« on: January 07, 2022, 06:20:08 pm »
Hi @all,

I wrote a little app for drawing charts. That is something new, isn't it?  :D
I am adding and editing series at runtime. Today I was gone for implementing the rendering over BGRA.
In order to get runtime-created TBarSeries rendered as ChocolateBar, I need to assign an event-handler, and that is the step where I got stuck.

Code: Pascal  [Select][+][-]
  1. procedure TfrmMain.AddSeries;
  2. var
  3.   ser: TBasicChartSeries;
  4. ..
  5.  
  6. begin
  7.  
  8. ...
  9.  
  10. if ser is TBarSeries then
  11.     begin
  12.       //this code gets executed
  13.       TBarSeries(ser).OnBeforeDrawBar := @BeforeDrawBarHandler;
  14.     end;
  15.     Chart.AddSeries(ser);
  16.  
  17.  
  18. ....
  19.  
  20.  
  21. procedure TfrmMain.BeforeDrawBarHandler(ASender: TBarSeries;
  22.   ACanvas: TCanvas; const ARect: TRect; APointIndex, AStackIndex: integer;
  23.   var ADoDefaultDrawing: boolean);
  24. begin
  25.   //this code never execute
  26.   ADoDefaultDrawing := False;
  27.   DrawChocolateBar(ASender, ACanvas, ARect, APointIndex, True);
  28. end;
  29.  

Any idea what I am doing wrong?

The app is based on the demos for TAChart with the addition of saving the whole work to file, copy the graph to the clipboard.
Screenshot is attached (just an example without much sense)

If the app gets usable, I will be glad to share it here.
https://gitlab.com/bobby100 - my Lazarus components and units
https://sourceforge.net/u/boban_spasic/profile/ - my open source apps

https://malzilla.org/ - remainder at my previous life as a web security expert

wp

  • Hero Member
  • *****
  • Posts: 9921
Re: Adding event to runtime-created series
« Reply #1 on: January 08, 2022, 07:37:53 pm »
You do not say what's the problem...

Comparing your code snippet with the bgra demo in the TAChart demo folder I see that you assign an event handler to OnBeforeDrawBar, but in the demo there is a handler for OnCustomDrawBar.

bobby100

  • Full Member
  • ***
  • Posts: 100
    • Malzilla
Re: Adding event to runtime-created series
« Reply #2 on: January 08, 2022, 07:45:44 pm »
Hi wp,

the problem is that the event does not get triggered - it remains the default rendering. It does not render through BGRA. Take a look at the comments in the code.

As for the TAChart demo - there are examples for both OnBeforeDrawBar and OnCustomDrawBar. In TAChart tutorial on the Wiki is also OnBeforeDrawBar.

Do I need to initialize something in order to get BGRA rendering?
https://gitlab.com/bobby100 - my Lazarus components and units
https://sourceforge.net/u/boban_spasic/profile/ - my open source apps

https://malzilla.org/ - remainder at my previous life as a web security expert

wp

  • Hero Member
  • *****
  • Posts: 9921
Re: Adding event to runtime-created series
« Reply #3 on: January 08, 2022, 11:05:44 pm »
Thanks for bringing my attention to this.

The OnBeforeDrawBar event of the TBarSeries has been deprecated for some time and has been replaced by the OnCustomDrawBar event. This new event is more flexible regarding the drawing backends (ChartDrawer).

In the transition time before the OnBeforeDrawBar event will be removed finally, both events will be available, but the OnBeforeDrawBar handler will be executed only when no OnCustomDrawBar handler is attached. Unfortunately I had forgotten to remove the old OnBeforeDrawBar code from the demo - just did this in the current Lazarus/main version.

I also updated the wiki tutorial about TAChart and BGRA (https://wiki.lazarus.freepascal.org/BGRABitmap_tutorial_TAChart).

bobby100

  • Full Member
  • ***
  • Posts: 100
    • Malzilla
Re: Adding event to runtime-created series
« Reply #4 on: January 08, 2022, 11:31:30 pm »
Thanks, but it didn't help.
Code: Pascal  [Select][+][-]
  1. procedure TfrmMain.BeforeDrawBarHandler(ASeries: TBarSeries;
  2.   ADrawer: IChartDrawer; const ARect: TRect; APointIndex, AStackIndex: Integer);
  3. var
  4.   ic: IChartTCanvasDrawer;
  5. begin
  6.   if not Supports(ADrawer, IChartTCanvasDrawer, ic) then
  7.     raise Exception.Create('This program requires a canvas drawer.');
  8.   DrawPhong3DBar(ASeries, ic.Canvas, ARect, APointIndex);
  9. end;  

This code gives the exception 'This program requires a canvas drawer'.
I use Lazarus 2.2.0 RC2. Is that the source of my problem?
https://gitlab.com/bobby100 - my Lazarus components and units
https://sourceforge.net/u/boban_spasic/profile/ - my open source apps

https://malzilla.org/ - remainder at my previous life as a web security expert

wp

  • Hero Member
  • *****
  • Posts: 9921
Re: Adding event to runtime-created series
« Reply #5 on: January 09, 2022, 12:36:15 am »
Don't mix up the two events. You did put the OnCustomDrawBar code into the OnBeforeDrawBar event.

So, either you use the old OnBeforeDrawEvent and then you should write:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Chart1BarSeries1BeforeDrawBar(ASender: TBarSeries;
  2.   ACanvas: TCanvas; const ARect: TRect; APointIndex, AStackIndex: Integer;
  3.   var ADoDefaultDrawing: Boolean);
  4. begin
  5.   ADoDefaultDrawing:= false;
  6.   DrawPhong3DBar(ASender, ACanvas, ARect, APointIndex);
  7. end;

Or you use the new OnCustomDrawEvent and here you should write:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Chart1BarSeries1CustomDrawBar(ASeries: TBarSeries;
  2.   ADrawer: IChartDrawer; const ARect: TRect; APointIndex, AStackIndex: Integer);
  3. var
  4.   ic: IChartTCanvasDrawer;
  5. begin
  6.   if not Supports(ADrawer, IChartTCanvasDrawer, ic) then
  7.     raise Exception.Create('This program requires a canvas drawer.');
  8.   DrawPhong3DBar(ASeries, ic.Canvas, ARect, APointIndex);
  9. end;
If you use both the OnCustomDrawBar handler will be executed.

Since you already use Laz 2.2 I recommend to pick the OnCustomDrawBar since the other event will be removed (not yet sure - maybe it will be gone already in Laz 2.4).

bobby100

  • Full Member
  • ***
  • Posts: 100
    • Malzilla
Re: Adding event to runtime-created series
« Reply #6 on: January 09, 2022, 08:59:02 am »
Sorry, it's a bit of a misunderstanding because of the handler's name. I did assign it to the right event, OnCustomDrawBar, I just didn't change the name of the handler procedure.

Sorry, old school here. I do not understand the concept of the interfaces and how to use them...
https://gitlab.com/bobby100 - my Lazarus components and units
https://sourceforge.net/u/boban_spasic/profile/ - my open source apps

https://malzilla.org/ - remainder at my previous life as a web security expert

wp

  • Hero Member
  • *****
  • Posts: 9921
Re: Adding event to runtime-created series
« Reply #7 on: January 09, 2022, 12:40:31 pm »
Did you attach a BGRA-GUIConnector to the chart?

If you did I can confirm that the example is not working because the BGRADrawer does not expose a Canvas. Trying to extend the example, but this will take some time...

bobby100

  • Full Member
  • ***
  • Posts: 100
    • Malzilla
Re: Adding event to runtime-created series
« Reply #8 on: January 09, 2022, 04:05:27 pm »
wp, you are the best  :D

Indeed, BGRA-GUIConnector was the problem.

btw. about your new examples in the Wiki - you need to add TADrawUtils in the uses for the OnCustomDrawBar example:

Code: Pascal  [Select][+][-]
  1. uses
  2.   TADrawerCanvas, TABGRAUtils, TADrawUtils;
  3.  
  4. procedure TForm1.Chart1BarSeries1CustomDrawBar(ASeries: TBarSeries;
  5.   ADrawer: IChartDrawer; const ARect: TRect; APointIndex, AStackIndex: Integer);
  6. var
  7.   ic: IChartTCanvasDrawer;
  8. begin
  9.   if not Supports(ADrawer, IChartTCanvasDrawer, ic) then
  10.     raise Exception.Create('This program requires a canvas drawer.');
  11.  
  12.   DrawPhong3DBar(ASeries, ic.Canvas, ARect, APointIndex);
  13. end;

Thank you very much.
https://gitlab.com/bobby100 - my Lazarus components and units
https://sourceforge.net/u/boban_spasic/profile/ - my open source apps

https://malzilla.org/ - remainder at my previous life as a web security expert

wp

  • Hero Member
  • *****
  • Posts: 9921
Re: Adding event to runtime-created series
« Reply #9 on: January 09, 2022, 07:37:38 pm »
So you removed the GUIConnector? OK, this way you can access the canvas because the chart is still painted on a standard LCL canvas. But of course, you do not get the anti-aliased lines of the BGRA drawer this way.

Maybe someone who knows BGRA better than me can show me how to paint the BGRA effects when the chart is painted by the BGRA drawer.

BTW, in Laz 2.2, TBarSeries has received several improvements, among them "DepthBrightnessDelta" which allows to simulate lighting of the top and side faces of 3D bars and to achieve similar effects like in the BGRA demo by the standard drawer. Another new feature is the "BarShape" which allows to draw cylindrical, conical, prismatic or pyramidal "bars" as well.

 

TinyPortal © 2005-2018