Delphi 在图表中存储对对象的引用
我将TeeChart与Delphi XE5结合使用,并利用BubbleSeries组件在图表中显示X/Y/Radius气泡 我正在使用我拥有的对象列表构建图表,动态计算这些对象的X/Y/半径值,并使用tbubleSeries.AddBubble方法插入它们 问题是当我想在相应气泡悬停/单击时对对象执行某些操作时,我使用TChartSeries.clicked方法来确定单击了哪个气泡,但返回的索引仅可用于确定气泡的xy/半径值,而不是由哪个对象生成的 也许我遗漏了一些简单的东西,因为这似乎是任何图表库都应该轻松处理的事情。我尝试使用AddBubble方法返回的索引,但该索引只有在执行另一个AddBubble调用之前才有效,此时,内部列表似乎被重新排序 编辑:被要求一些代码,在这里Delphi 在图表中存储对对象的引用,delphi,vcl,delphi-xe5,teechart,Delphi,Vcl,Delphi Xe5,Teechart,我将TeeChart与Delphi XE5结合使用,并利用BubbleSeries组件在图表中显示X/Y/Radius气泡 我正在使用我拥有的对象列表构建图表,动态计算这些对象的X/Y/半径值,并使用tbubleSeries.AddBubble方法插入它们 问题是当我想在相应气泡悬停/单击时对对象执行某些操作时,我使用TChartSeries.clicked方法来确定单击了哪个气泡,但返回的索引仅可用于确定气泡的xy/半径值,而不是由哪个对象生成的 也许我遗漏了一些简单的东西,因为这似乎是任何图
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;
我会使用一个通用的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.
最后,在您的源中使用它:
将BubbleSeriesTention添加到VclTee.BubbleCh之后的uses列表中
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.
类型
TForm4=类(TForm)
图1:TChart;
泡泡系列:t泡泡系列;
过程表单创建(发送方:ToObject);
过程图表1移动鼠标(发送方:ToObject;Shift:TShiftState;X,Y:整数);
私有的
{私有声明}
公众的
{公开声明}
结束;
变量
表格4:TForm4;
实施
{$R*.dfm}
程序TForm4.Chart1MouseMove(发送方:TObject;移位:TShiftState;X,Y:整数);
变量
索引:整数;
气泡:t气泡;
开始
索引:=泡泡系列。单击(X,Y);
如果指数<0,则
出口
Bouble:=BubbleSeries.BoubleList.ElementFormChartIndex(索引);
标题:=Bouble.LabelText;
结束;
程序TForm4.FormCreate(发送方:TObject);
变量
i:整数;
开始
//添加虚拟数据
对于i:=0到9 do
AddBubble(tbuble.Create(i));
结束;
结束。
此解决方案的优点是,您可以随时访问对象,当您的BubbleSeries被销毁时,用于计算其中元素的对象也会被销毁。并为您提供一种垃圾收集您可以像这样利用未使用的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]);
特别是不起作用的代码:鼠标定位到Bouble对象。添加了一些代码!希望问题现在清楚了。嗯,这真的有效吗?因为继承的AddBubble将重新调整内部实现并多次返回相同的索引,所以它不会遇到同样的问题吗?不会,因为我将内部索引存储在对象上。如果可以将其设置为mail pelase,则在失败的地方提供som realt数据。是否使用标签和颜色bubble属性?我不使用标签和所有气泡都有相同的样式(从系列的表单设计师那里设置)。嘿,丑陋,但我喜欢它。如果没有更干净的解决方案,我就用这个。嗯,有没有办法让x值在使用标签时仍然显示在x轴上?我不想把轴心完全隐藏起来一个非常丑陋的黑客,它不是一个黑客。这类似于使用标记属性来存储用户数据。气泡没有标记或其他用户数据属性,作者不打算使用辅助气泡属性。为什么不让它们工作?@MBo这是错误的,TBubbleSeries有Tag(整数)和TagObject(TObject)属性。
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]);