📄 ipiechart.pas
字号:
procedure TiPieChart.SetStartDegrees(const Value: Integer);
var
TempValue : Integer;
begin
TempValue := Value;
while TempValue > 359 do
TempValue := TempValue - 360;
while TempValue < -359 do
TempValue := TempValue + 360;
if FStartDegrees <> TempValue then
begin
FStartDegrees := TempValue;
InvalidateChange;
end;
end;
//****************************************************************************************************************************************************
procedure TiPieChart.DefineProperties(Filer: TFiler);
begin
inherited DefineProperties(Filer);
Filer.DefineProperty('Items', ReadItems, WriteItems, DoWriteItems);
end;
//****************************************************************************************************************************************************
procedure TiPieChart.ReadItems(Reader: TReader);
var
iPercentItemObject : TiPercentItemObject;
begin
ClearList;
Reader.ReadListBegin;
while not Reader.EndOfList do
begin
iPercentItemObject := TiPercentItemObject.Create;
FItemList.AddObject('', iPercentItemObject);
iPercentItemObject.Title := Reader.ReadString;
Reader.ReadListBegin;
iPercentItemObject.Color := Reader.ReadInteger;
iPercentItemObject.Value := Reader.ReadFloat;
Reader.ReadListEnd
end;
Reader.ReadListEnd;
end;
//****************************************************************************************************************************************************
procedure TiPieChart.WriteItems(Writer: TWriter);
var
x : Integer;
iPercentItemObject : TiPercentItemObject;
begin
Writer.WriteListBegin;
for x := 0 to FItemList.Count - 1 do
begin
iPercentItemObject := FItemList.Objects[x] as TiPercentItemObject;
Writer.WriteString (iPercentItemObject.Title);
Writer.WriteListBegin;
Writer.WriteInteger(iPercentItemObject.Color);
Writer.WriteFloat(iPercentItemObject.Value);
Writer.WriteListEnd;
end;
Writer.WriteListEnd;
end;
//****************************************************************************************************************************************************
function TiPieChart.DoWriteItems: Boolean;
begin
Result := FItemList.Count <> 0;
end;
//****************************************************************************************************************************************************
procedure TiPieChart.iPaintTo(Canvas: TCanvas);
var
PieRect : TRect;
PieMaxSize : Integer;
ATextString : String;
ATextRect : TRect;
AWidth : Integer;
YPoint : Integer;
x : Integer;
iPercentItemObject : TiPercentItemObject;
LegendLeft : Integer;
LegendRowHeight : Integer;
LegendHeight : Integer;
TotalValue : Double;
ItemPercent : Double;
PreviousStartDegrees : Double;
CurrentRangeDegrees : Double;
{$ifdef iVCL}ArcStartPoint : TPoint;{$endif}
{$ifdef iVCL}ArcStopPoint : TPoint;{$endif}
CenterPoint : TPoint;
TitleHeight : Integer;
TitleWidth : Integer;
TitleCenterX : Integer;
MaxTitleWidth : Integer;
MaxValueWidth : Integer;
MaxPercentWidth : Integer;
ShowTitle : Boolean;
begin
with Canvas do
begin
DrawBackGround(Canvas, BackGroundColor);
Font.Assign(FTitleFont);
Brush.Style := bsSolid;
Pen.Style := psSolid;
ShowTitle := Length(Trim(FTitleText)) > 0;
if ShowTitle then TitleHeight := TextHeight('ABC') + FTitleMargin else TitleHeight := 0;
if FItemList.Count <> 0 then
begin
Font.Assign(FLegendFont);
TotalValue := 0;
MaxTitleWidth := 0;
MaxValueWidth := 0;
MaxPercentWidth := 0;
for x := 0 to FItemList.Count - 1 do
TotalValue := TotalValue + (FItemList.Objects[x] as TiPercentItemObject).Value;
for x := 0 to FItemList.Count - 1 do
begin
iPercentItemObject := FItemList.Objects[x] as TiPercentItemObject;
AWidth := TextWidth(Format('%.' + IntToStr(FLegendValuePrecision) + 'f', [iPercentItemObject.Value]));
if AWidth > MaxValueWidth then MaxValueWidth := AWidth;
if TotalValue = 0 then
AWidth := TextWidth(Format('%.' + IntToStr(FLegendPercentPrecision) + 'f', [1/FItemList.Count*100]) + '%')
else
AWidth := TextWidth(Format('%.' + IntToStr(FLegendPercentPrecision) + 'f', [iPercentItemObject.Value/TotalValue*100]) + '%');
if AWidth > MaxPercentWidth then MaxPercentWidth := AWidth;
AWidth := TextWidth(Trim(iPercentItemObject.Title));
if AWidth > MaxTitleWidth then MaxTitleWidth := AWidth;
end;
PieMaxSize := Height - 2*FOuterMargin - TitleHeight;
if (PieMaxSize mod 2) = 1 then PieMaxSize := PieMaxSize - 1;
PieRect := Rect(FOuterMargin, FOuterMargin, FOuterMargin + PieMaxSize - 1, FOuterMargin + PieMaxSize - 1);
CenterPoint := Point((PieRect.Right + PieRect.Left) div 2, (PieRect.Bottom + PieRect.Top) div 2);
PreviousStartDegrees := FStartDegrees;
LegendLeft := PieRect.Right + FLegendMargin;
LegendRowHeight := TextHeight('ABC');
LegendHeight := (FItemList.Count * LegendRowHeight);
YPoint := (PieRect.Top + PieRect.Bottom) div 2 - LegendHeight div 2 + LegendRowHeight div 2;
Font.Assign(FLegendFont);
for x := 0 to FItemList.Count - 1 do
begin
iPercentItemObject := FItemList.Objects[x] as TiPercentItemObject;
Brush.Color := iPercentItemObject.Color;
Brush.Style := bsSolid;
Pen.Color := iPercentItemObject.Color;
if TotalValue = 0 then
ItemPercent := 1/FItemList.Count
else
ItemPercent := iPercentItemObject.Value / TotalValue;
if ABS(ItemPercent) > 0.01 then
begin
CurrentRangeDegrees := 360 * ItemPercent;
{$ifdef iVCL}
ArcStartPoint := GetXYRadPoint(PreviousStartDegrees, (PieMaxSize/2)+10, CenterPoint);
ArcStopPoint := GetXYRadPoint(PreviousStartDegrees + CurrentRangeDegrees, (PieMaxSize/2)+10, CenterPoint);
Pie(PieRect.Left, PieRect.Top, PieRect.Right, PieRect.Bottom, ArcStartPoint.X, ArcStartPoint.Y, ArcStopPoint.X, ArcStopPoint.Y);
{$endif}
{$ifdef iCLX}
Pie(PieRect.Left, PieRect.Top, PieRect.Right, PieRect.Bottom, Round(PreviousStartDegrees*16), Round(CurrentRangeDegrees*16));
{$endif}
PreviousStartDegrees := PreviousStartDegrees + CurrentRangeDegrees;
end;
Brush.Color := iPercentItemObject.Color;
Pen.Color := iPercentItemObject.Color;
Rectangle(LegendLeft + 5, YPoint - 2, LegendLeft + 15, YPoint + 2);
Brush.Style := bsClear;
ATextString := Trim(iPercentItemObject.Title);
ATextRect := Rect(LegendLeft + 20, YPoint - LegendRowHeight div 2, Width - 5, YPoint + LegendRowHeight div 2);
TextOut(ATextRect.Left, ATextRect.Top, ATextString);
if FLegendShowValue then
begin
ATextString := Format('%.' + IntToStr(FLegendValuePrecision) + 'f', [iPercentItemObject.Value]);
ATextRect.Left := ATextRect.Left + MaxTitleWidth + FLegendValueMargin;
ATextRect.Right := ATextRect.Left + MaxValueWidth;
TextOut(ATextRect.Right - TextWidth(ATextString), ATextRect.Top, ATextString);
end
else
begin
ATextRect.Left := ATextRect.Left + MaxTitleWidth;
ATextRect.Right := ATextRect.Left;
end;
if FLegendShowPercent then
begin
if TotalValue = 0 then
ATextString := Format('%.' + IntToStr(FLegendPercentPrecision) + 'f', [1/FItemList.Count*100]) + '%'
else
ATextString := Format('%.' + IntToStr(FLegendPercentPrecision) + 'f', [iPercentItemObject.Value/TotalValue*100]) + '%';
ATextRect.Left := ATextRect.Right + FLegendPercentMargin;
ATextRect.Right := ATextRect.Left + MaxPercentWidth;
TextOut(ATextRect.Right - TextWidth(ATextString), ATextRect.Top, ATextString);
end;
YPoint := YPoint + LegendRowHeight;
end;
end
else
begin
PieRect.Left := 0;
PieRect.Right := Width;
PieRect.Bottom := Height div 2;
end;
if ShowTitle then
begin
Font.Assign(FTitleFont);
ATextString := Trim(FTitleText);
case FTitleHorizontalAlignment of
ithaCenterDisplay : TitleCenterX := (PieRect.Left + PieRect.Right) div 2;
ithaCenterControl : TitleCenterX := Width div 2;
else TitleCenterX := 0;
end;
TitleWidth := TextWidth(FTitleText);
Brush.Style := bsClear;
TextOut(TitleCenterX - TitleWidth div 2, PieRect.Bottom + FTitleMargin, ATextString);
end;
end;
end;
//****************************************************************************************************************************************************
{$ifdef iVCL}
function TiPieChart.OPCNewDataSpecial(iOPCItem: TiOPCItem): Boolean;
var
x : Integer;
begin
Result := inherited OPCNewDataSpecial(iOPCItem);
for x := 0 to FItemList.Count-1 do
if UpperCase('Item(' + IntToStr(x) + ').Value') = UpperCase(iOPCItem.PropertyName) then
begin
Result := True;
SetItemValue(x, iOPCItem.Data);
end;
end;
//****************************************************************************************************************************************************
procedure TiPieChart.UpdateOPCSpecialList;
var
x : Integer;
begin
if not Assigned(OPCSpecialList) then Exit;
OPCSpecialList.Clear;
for x := 0 to FItemList.Count-1 do
OPCSpecialList.Add('Item(' + IntToStr(x) + ').Value');
end;
{$endif}
//****************************************************************************************************************************************************
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -