我正在使用 Rad Studio XE3 附带的 TeeChart 版本。
TeeChart 提供了一个 TChartSeries 事件,当鼠标指针移过系列线时会触发该事件。我使用此事件在指针下显示系列的名称。
问题是,给一个 1 像素宽的系列线,很难让指针准确地越过该线。是否有某种方法可以向事件添加“填充”,以便在行的每一侧触发 X 个像素?
还是有其他方法可以做到这一点?
我正在向 Line (TLineSeries) 和 FastLine (TFastLineSeries) 类添加一个新属性来完成此操作。
Series1.ClickTolerance := 4; // <-- number of pixels around mouse XY
默认值为零(鼠标 XY 应该正好在该线上),就像当前的行为一样。
作为一种解决方法,如果您使用 TLineSeries,指针可以显示在线点位置,并且内部“单击”函数将考虑指针大小:
Series1.Pointer.Visible:=True;
而对于更多的自定义控件,下面的代码与用于检测鼠标点击的内部代码非常相似。Tolerance 常数指定要考虑“在线”的额外像素数。
procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
const
Tolerance=4;
var Clicked,
t : Integer;
Position,
P,Old : TPoint;
begin
Clicked:= -1;
Position.X:=X;
Position.Y:=Y;
for t:=Series1.FirstValueIndex to Series1.LastValueIndex do
begin
P.X:=Series1.CalcXPos(t);
P.Y:=Series1.CalcYPos(t);
if t>Series1.FirstValueIndex then
if PointInLine(Position,P.X,P.Y,Old.X,Old.Y,Tolerance) then
begin
Clicked:=t;
break;
end;
Old:=P;
end;
if Clicked = -1 then
Caption:=''
else
Caption:=IntToStr(Clicked);
end;
您可以使用该PointInLineTolerance
功能在OnMouseMove
事件中检查它。但是,您必须手动循环系列点以将系列值转换为像素并将它们传递给此函数。
uses Series;
procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
Chart1.View3D:=false;
for i:=0 to 5 do
Chart1.AddSeries(TLineSeries).FillSampleValues;
end;
procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var series, valueIndex: Integer;
P0, P1: TPoint;
begin
Chart1.Draw;
for series:=0 to Chart1.SeriesCount-1 do
with Chart1[series] do
for valueIndex:=FirstValueIndex to LastValueIndex-1 do
begin
P0.X:=CalcXPos(valueIndex);
P0.Y:=CalcYPos(valueIndex);
P1.X:=CalcXPos(valueIndex+1);
P1.Y:=CalcYPos(valueIndex+1);
if PointInLineTolerance(Point(X, Y), P0.X, P0.Y, P1.X, P1.Y, 5) then
begin
Chart1.Canvas.TextOut(X+5,Y-10,'Series ' + IntToStr(series));
exit;
end;
end;
end;