【问题标题】:Storing reference to object in TeeChart在 TeeChart 中存储对对象的引用
【发布时间】:2015-02-02 09:15:51
【问题描述】:

我将 TeeChart 与 Delphi XE5 一起使用,并利用 BubbleSeries 组件在图表中显示 X/Y/Radius 气泡。

我正在使用我拥有的对象列表构建图表,动态计算这些对象的 X/Y/Radius 值并使用 TBubbleSeries.AddBubble 方法插入它们。

问题是当我想在相应的气泡悬停/单击/等时对对象执行一些操作时。我使用 TChartSeries.Clicked 方法来找出单击了哪个气泡,但我返回的索引仅可用于找出气泡的 xy/半径值,而不是源自它的对象。

也许我遗漏了一些简单的东西,因为这似乎是任何图表库都应该轻松处理的东西。我尝试使用 AddBubble 方法返回的索引,但该索引仅在对 AddBubble 执行另一个调用之前有效,此时,内部列表似乎被重新排序。

编辑:被要求提供一些代码,在这里!

procedure TBubbleReportForm.ChartMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  Index: Integer;
  Device: TDevice;
begin

  Index := BubbleSeries.Clicked(X,Y);

  if Index = -1 then
  begin
    BubbleChart.ShowHint := False;
    Exit;
  end;

  // This does not work as indexing does seems to correspond to the order which the bubbles was added.
  Device := FDevices[Index];


  BubbleChart.Hint := Device.Name;
  BubbleChart.ShowHint := True;

end;



procedure TBubbleReportForm.FormCreate(Sender: TObject);
var
  Device: TDevice;
begin


  BubbleChart.OnMouseMove := ChartMouseMove;

  // FDevices is of TObjectList type.
  for Device in FDevices do
  begin

    BubbleSeries.AddBubble(Device.CalculateXVal,Device.CalculateYVal,Device.CalculateRadius);

  end;

end;

【问题讨论】:

  • 您是否使用了标签和颜色气泡属性?
  • 我没有使用标签,所有气泡都具有相同的样式(从系列的表单设计器中设置)。

标签: delphi vcl delphi-xe5 teechart


【解决方案1】:

我会使用一个通用 TObjectList。或 TObjectList 的后代。

首先执行您的 BoubleObject,并列出它们。在以下示例中,我刚刚使用了一个虚拟实现:

unit BubbleU;

interface

uses

  System.Generics.Collections, System.SysUtils, Vcl.Graphics;

{$M+}

type
  TBubble = class
  private
    FX: Double;
    FRadius: Double;
    FY: Double;
    FLabelText: String;
    FColor: TColor;
    FIndex: Integer;
    FChartIndex: Integer;
    procedure SetChartIndex(const Value: Integer);
  protected
    procedure DoCalculation;
  public
    constructor Create(aIndex: Integer); reintroduce;
  published
    property X: Double read FX;
    property Y: Double read FY;
    property Radius: Double read FRadius;
    property LabelText: String read FLabelText;
    property Color: TColor read FColor;
    property ChartIndex: Integer read FChartIndex write SetChartIndex;
  end;

  TBubbleList = class(TObjectList<TBubble>)
  public
    function ElementFormChartIndex(ChartIndex: Integer): TBubble; overload;
  end;

implementation

{ TBubble }

constructor TBubble.Create(aIndex: Integer);
begin
  inherited Create;
  FIndex := aIndex;
  DoCalculation;
end;

procedure TBubble.DoCalculation;
begin
  FX := FIndex;
  FY := FIndex;
  FRadius := 1;
  FColor := clRed;
  FLabelText := 'Index: ' + FIndex.ToString;
end;

procedure TBubble.SetChartIndex(const Value: Integer);
begin
  FChartIndex := Value;
end;

{ TBubbleList }

function TBubbleList.ElementFormChartIndex(ChartIndex: Integer): TBubble;
var
  Element : TBubble;
begin
  for Element in Self do
    if Element.FChartIndex = ChartIndex then
      Exit(element);

  Exit(nil);
end;
end.

下一步扩展您的 TBubbleSeries

unit BubbleSeriesExtention;

interface

uses
  System.Classes, System.SysUtils,
  VclTee.BubbleCh,
  BubbleU;

type
  TBubbleSeries = class(VclTee.BubbleCh.TBubbleSeries)
  strict private
    FBoubleList: TBubbleList;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function AddBubble(aBubble: TBubble): Integer; reintroduce;
  published
    property BoubleList : TBubbleList read FBoubleList;
  end;

implementation

{ TBubbleSeries }

function TBubbleSeries.AddBubble(aBubble: TBubble): Integer;
begin
  aBubble.ChartIndex := Inherited AddBubble(aBubble.X, aBubble.Y, aBubble.Radius, aBubble.LabelText, aBubble.Color);
  FBoubleList.Add(aBubble);
  Result := aBubble.ChartIndex;
end;

constructor TBubbleSeries.Create(AOwner: TComponent);
begin
  inherited;
  FBoubleList := TBubbleList.Create(True);
end;

destructor TBubbleSeries.Destroy;
begin
  FreeAndNil(FBoubleList);
  inherited;
end;

end.

最后在你的 from: 中使用它:

在 VclTee.BubbleCh 之后的使用列表中添加 BubbleSeriesExtention

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VclTee.TeeGDIPlus, VclTee.TeEngine,
  VclTee.Series, VclTee.BubbleCh, Vcl.ExtCtrls, VclTee.TeeProcs, VclTee.Chart,

  BubbleU, BubbleSeriesExtention;

并使用它:

type
  TForm4 = class(TForm)
    Chart1: TChart;
    BubbleSeries: TBubbleSeries;
    procedure FormCreate(Sender: TObject);
    procedure Chart1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

procedure TForm4.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  Index: Integer;
  Bouble: TBubble;

begin
  Index := BubbleSeries.Clicked(X, Y);

  if index < 0 then
    exit;

  Bouble := BubbleSeries.BoubleList.ElementFormChartIndex(Index);
  Caption := Bouble.LabelText;
end;

procedure TForm4.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  //Add dummy data
  for i := 0 to 9 do
    BubbleSeries.AddBubble(TBubble.Create(i));
end;

end.

此解决方案的优势在于您始终可以访问您的对象,并且当您的 BubbleSeries 被破坏时,用于计算其中元素的对象也是如此。并给你一种垃圾收集方式

【讨论】:

  • 尤其是不起作用的代码:鼠标定位到 Bouble 对象。
  • 添加了一些代码!希望问题现在已经清楚了。
  • 嗯,这真的有用吗?不会因为 Inherited AddBubble 会重新洗牌内部实现并多次返回相同的索引而遭受同样的问题吗?
  • 不,它不会因为我将内部索引存储在它自己的对象上。
  • 如果你能做到,请在邮件失败的地方提供一些房地产数据。
【解决方案2】:

您可以像这样利用未使用的 AXLabel 参数:

for DevIndex := 0 to DeviceCount - 1 do begin
    Device := FDevices[DevIndex]; 
    BubbleSeries.AddBubble(Device.CalculateXVal,Device.CalculateYVal, Device.CalculateRadius, IntToStr(DevIndex));
end; 

// to avoid labels' text ox X-Axis:
Chart1.BottomAxis.LabelStyle := talValue; 

  //in Clicked:
   DeviceIndex := StrToInt(BubbleSeries.Labels[Index]);

【讨论】:

  • 嘿,丑,但我喜欢。如果没有出现更清洁的解决方案,我会使用它。
  • 嗯,有什么方法可以让使用标签时x值仍然显示在x轴上?我不想完全隐藏轴..
  • 一个极其丑陋的黑客。
  • 这不是黑客。就像标记属性用来存储用户数据一样。气泡没有标签或其他用户数据属性,作者不会使用辅助气泡属性。为什么不让它们发挥作用?
  • @MBo 错了,TBubbleSeries 有 Tag (integer) 和 TagObject (TObject) 属性。
猜你喜欢
  • 2014-02-16
  • 2012-10-28
  • 1970-01-01
  • 2016-06-16
  • 2014-08-11
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
相关资源
最近更新 更多