Delphi + TeeChart:如何获得饼图系列值的图例复选框?

时间:2017-05-11 10:03:51

标签: delphi charts pie-chart teechart

我希望允许用户通过在每个系列的值前面显示一个复选框来选择带有饼系列值的图表中显示的值。

可以选择在每个图例项目附近显示一个复选框,但它只适用于系列,而不是系列中的值;并且你只能在一个馅饼中拥有一系列价值。

有没有人知道如何实现这个目标?

1 个答案:

答案 0 :(得分:2)

您可以手动绘制自定义图例。但是,你应该做一些技巧:

  • 使用虚拟系列来存储原始值并在图例中显示这些值。
  • 从图例中单击的主要系列中删除值,并注意索引和颜色。

这是一个例子,即使是鼠标悬停:

example

uses Series, TeCanvas, Math;

var pieSeries: TPieSeries;
    dummySeries: TPieSeries;
    itemRect: array of TRect;
    itemIndex: Integer;

procedure TForm1.Chart1AfterDraw(Sender: TObject);
var i, tmpH, tmpW: Integer;
    tmpR, tmpS: TRect;
begin
  with Chart1.Canvas do
  begin
    AssignFont(Chart1.Legend.Font);
    AssignBrush(Chart1.Legend.Brush);

    tmpW:=0;
    tmpH:=0;
    for i:=0 to dummySeries.Count-1 do
    begin
      tmpW:=Max(TextWidth(dummySeries.LegendString(i, Chart1.Legend.TextStyle)), tmpW);
      tmpH:=Max(TextHeight(dummySeries.LegendString(i, Chart1.Legend.TextStyle)), tmpH);
    end;

    Inc(tmpW, Chart1.Legend.Symbol.Width + TeeCheckBoxSize + 8);

    tmpR.Left:=Chart1.Width-tmpW-10;
    tmpR.Top:=50;
    tmpR.Right:=tmpR.Left+tmpW;
    tmpR.Bottom:=tmpR.Top + ((tmpH+4) * dummySeries.Count) + 4;

    Rectangle(tmpR);

    Inc(tmpR.Left, 4);
    tmpS.Left:=tmpR.Left+TeeCheckBoxSize+4;
    tmpS.Right:=tmpS.Left+TeeCheckBoxSize;
    for i:=0 to dummySeries.Count-1 do
    begin
      Brush.Color:=OperaPalette[i];
      Inc(tmpR.Top, 4);

      DrawCheckBox(tmpR.Left, tmpR.Top, not dummySeries.IsNull(i), clNone);

      if i=itemIndex then
      begin
        Pen.Color:=clRed;
        Font.Color:=clRed;
      end
      else
      begin
        Pen.Color:=Chart1.Legend.Symbol.Pen.Color;
        Font.Color:=Chart1.Legend.Font.Color;
      end;

      tmpS.Top:=tmpR.Top+1;
      tmpS.Bottom:=tmpS.Top+TeeCheckBoxSize;
      Rectangle(tmpS);

      TextOut(tmpS.Right + 2, tmpR.Top, StringReplace(dummySeries.LegendString(i, Chart1.Legend.TextStyle), TeeColumnSeparator, ' ', [rfReplaceAll, rfIgnoreCase]));

      itemRect[i]:=Rect(tmpR.Left, tmpS.Top, tmpR.Right, tmpS.Bottom);

      Inc(tmpR.Top, tmpH);
    end;
  end;
end;

procedure TForm1.Chart1Click(Sender: TObject);
var i, j: Integer;
begin
  if itemIndex>-1 then
  begin
     dummySeries.SetNull(itemIndex, not dummySeries.IsNull(itemIndex));

     pieSeries.CheckDataSource;

     for i:=pieSeries.Count-1 downto 0 do
       if pieSeries.IsNull(i) then
          pieSeries.Delete(i);

     //Fix colors
     j:=0;
     for i:=0 to dummySeries.Count-1 do
       if not dummySeries.IsNull(i) then
       begin
         pieSeries.ValueColor[j]:=OperaPalette[i];
         Inc(j);
       end;
  end;
end;

procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var i, j: Integer;
begin
  itemIndex:=-1;
  for i:=0 to length(itemRect)-1 do
    if PointInRect(itemRect[i], X, Y) then
    begin
      itemIndex:=i;
      break;
    end;

  if itemIndex>-1 then
  begin
    if dummySeries.IsNull(itemIndex) then
       pieSeries.Selected.HoverIndex:=-1
    else
    begin
      j:=0;
      for i:=0 to itemIndex-1 do
        if not dummySeries.IsNull(i) then
          Inc(j);

      pieSeries.Selected.HoverIndex:=j;
    end;
  end;

  Chart1.CancelMouse:=True;
  Chart1.Repaint;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  pieSeries:=Chart1.AddSeries(TPieSeries) as TPieSeries;
  pieSeries.FillSampleValues;

  for i:=0 to pieSeries.Count-1 do
    pieSeries.ValueColor[i]:=OperaPalette[i];

  dummySeries:=CloneChartSeries(pieSeries) as TPieSeries;
  dummySeries.ParentChart:=nil;

  pieSeries.DataSource:=dummySeries;

  Chart1.Legend.Visible:=False;
  Chart1.MarginRight:=20;

  SetLength(itemRect, dummySeries.Count);

  itemIndex:=-1;
end;