Recent

Author Topic: Add Image to TChart Component  (Read 835 times)

nullpointer

  • New member
  • *
  • Posts: 18
  • impossible is nothing
    • The Userman
Add Image to TChart Component
« on: May 08, 2018, 03:55:31 pm »
hello, i am learning to use tchart components in lazarus. is possible to change the country name with the image in the following example chart. or is there any other alternative?


wp

  • Hero Member
  • *****
  • Posts: 5156
Re: Add Image to TChart Component
« Reply #1 on: May 08, 2018, 05:21:01 pm »
Which "image" of a country do you mean?

If you are talking about the flags then you can try the attached demo. It has the flag icons of each country in an image list sorted such that the image index corresponds to the x value (I hope I sorted out the order correctly... - the icons are taken from the FatCow icon collection).

Painting of the images is done in the event OnAfterDraw which is called after the entire internal chart has been painted. To make space for the flags I moved the x axis up by increasing the "Margin" of the Chart's BottomAxis to 24. the count of axis labels is given by Chart.BottomAxis.ValueCount, information on the labels can be extracted as Chart.BottomAxis.Value[ i ], where i is the index of the label - and in this particular example also the index of the image in the image list. The Value is a TChartValueText record consisting of the elements FText and FValue - FValue is the position of the label in the units displayed along the axis. To find the pixel coordinates we must call the conversion function GraphToImage of the Chart. If axis transfomrations are involved also the conversion from axis to graph coordinates must be invoked.

The bitmap can be extracted from the imagelist by calling the GetBitmap method. But since the OnAfterDraw event does not paint on a canvas but takes advantage of the Chart drawers it must be converted to a TLazIntfImage.

The is the entire painting routine:
Code: Pascal  [Select]
  1. procedure TForm1.Chart1AfterDraw(ASender: TChart; ADrawer: IChartDrawer);
  2. var
  3.   i: Integer;
  4.   item: TChartValueText;
  5.   ximg: Integer;
  6.   xgr: Double;
  7.   bmp: TBitmap;
  8.   intfimg: TLazIntfImage;
  9. begin
  10.   bmp := TBitmap.Create;
  11.   for i:=0 to Chart1.BottomAxis.ValueCount-1 do begin
  12.     // Find out where the axis label is
  13.     item := Chart1.BottomAxis.Value[i];
  14.     // ... convert position to screen pixel coordinates
  15.     xgr := Chart1BarSeries1.AxisToGraphX(item.FValue);
  16.     ximg := Chart1.XGraphToImage(xgr);
  17.     // Extract the flag icon
  18.     ImageList1.GetBitmap(i, bmp);
  19.     // ... convert to a TFPCustomImage needed by the drawer
  20.     intfimg := bmp.CreateIntfImage;
  21.     // and paint the image
  22.     ADrawer.PutImage(ximg - bmp.Width div 2, ClientHeight - bmp.Height-8, intfimg);
  23.     intfimg.Free;
  24.   end;
  25.   bmp.Free;
  26. end;  
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

nullpointer

  • New member
  • *
  • Posts: 18
  • impossible is nothing
    • The Userman
Re: Add Image to TChart Component
« Reply #2 on: May 09, 2018, 02:59:16 pm »
Amazing. Thank u so much wp. great solution. you save my time.

I see the image is 16x16. is it possible to change the image size to 32x32?

wp

  • Hero Member
  • *****
  • Posts: 5156
Re: Add Image to TChart Component
« Reply #3 on: May 09, 2018, 03:08:06 pm »
Of course. The FatCows icon collection offers the same icons also in 32x32. Set Width and Height of the ImageList to 32, doubleclick on the ImageList and load the corresponding icons from http://www.fatcow.com/free-icons. Then you must increase the distance between the x axis and the bottom edge of the chart component (property Margin). That's all (probably...).
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

nullpointer

  • New member
  • *
  • Posts: 18
  • impossible is nothing
    • The Userman
Re: Add Image to TChart Component
« Reply #4 on: May 09, 2018, 03:13:10 pm »
thanks for your solution, wp. I just tried it. I think it's been solved.  :)