Adding event to runtime-created series lazarus / 55-TAChart ---------------------------------------------------------------------- bobby100 · 2022-01-07 17:20 Hi @all, I wrote a little app for drawing charts. That is something new, isn't it?  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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfrmMain.AddSeries;var  ser: TBasicChartSeries;.. begin ... if ser is TBarSeries then    begin      //this code gets executed      TBarSeries(ser).OnBeforeDrawBar := @BeforeDrawBarHandler;    end;    Chart.AddSeries(ser);  ....  procedure TfrmMain.BeforeDrawBarHandler(ASender: TBarSeries;  ACanvas: TCanvas; const ARect: TRect; APointIndex, AStackIndex: integer;  var ADoDefaultDrawing: boolean);begin  //this code never execute  ADoDefaultDrawing := False;  DrawChocolateBar(ASender, ACanvas, ARect, APointIndex, True);end; 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. ---------------------------------------------------------------------- wp · 2022-01-08 18:37 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 · 2022-01-08 18:45 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? ---------------------------------------------------------------------- wp · 2022-01-08 22:05 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 · 2022-01-08 22:31 Thanks, but it didn't help. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfrmMain.BeforeDrawBarHandler(ASeries: TBarSeries;  ADrawer: IChartDrawer; const ARect: TRect; APointIndex, AStackIndex: Integer);var  ic: IChartTCanvasDrawer;begin  if not Supports(ADrawer, IChartTCanvasDrawer, ic) then    raise Exception.Create('This program requires a canvas drawer.');  DrawPhong3DBar(ASeries, ic.Canvas, ARect, APointIndex);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? ---------------------------------------------------------------------- wp · 2022-01-08 23:36 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Chart1BarSeries1BeforeDrawBar(ASender: TBarSeries;  ACanvas: TCanvas; const ARect: TRect; APointIndex, AStackIndex: Integer;  var ADoDefaultDrawing: Boolean);begin  ADoDefaultDrawing:= false;  DrawPhong3DBar(ASender, ACanvas, ARect, APointIndex);end; Or you use the new OnCustomDrawEvent and here you should write: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Chart1BarSeries1CustomDrawBar(ASeries: TBarSeries;   ADrawer: IChartDrawer; const ARect: TRect; APointIndex, AStackIndex: Integer);var  ic: IChartTCanvasDrawer;begin  if not Supports(ADrawer, IChartTCanvasDrawer, ic) then    raise Exception.Create('This program requires a canvas drawer.');  DrawPhong3DBar(ASeries, ic.Canvas, ARect, APointIndex);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 · 2022-01-09 07:59 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... ---------------------------------------------------------------------- wp · 2022-01-09 11:40 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 · 2022-01-09 15:05 wp, you are the best  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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses   TADrawerCanvas, TABGRAUtils, TADrawUtils; procedure TForm1.Chart1BarSeries1CustomDrawBar(ASeries: TBarSeries;   ADrawer: IChartDrawer; const ARect: TRect; APointIndex, AStackIndex: Integer);var  ic: IChartTCanvasDrawer;begin  if not Supports(ADrawer, IChartTCanvasDrawer, ic) then    raise Exception.Create('This program requires a canvas drawer.');   DrawPhong3DBar(ASeries, ic.Canvas, ARect, APointIndex);end; Thank you very much. ---------------------------------------------------------------------- wp · 2022-01-09 18:37 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.