Hi,
I have a application where I show volume distributions using stacked bars, as in the attached screenshot.
I am displaying the volumes using the Marks but I am having some difficulty getting them in a readable position.
Ideally I would like to have the Marks centered on each bar value.
Is there any way to achieve this ?
Thank you.
Centered Marks on Stacked Bars
-
- Newbie
- Posts: 23
- Joined: Tue Feb 10, 2009 12:00 am
Centered Marks on Stacked Bars
- Attachments
-
- iqo2_cal1.gif (24.18 KiB) Viewed 11298 times
Re: Centered Marks on Stacked Bars
Hi,
The MarksOnBar property was introduced to do this. Setting it to true and combining it with with MarksLocation to mlCenter should do it.
But I'm afraid this new feature doesn't work fine with Stacked Bars. This is a know issue already in the wish list to be implemented in future releases (TV52015085).
In the meanwhile you could modify the marks positions manually as here, or just draw the marks manually with custom drawing methods.
The MarksOnBar property was introduced to do this. Setting it to true and combining it with with MarksLocation to mlCenter should do it.
But I'm afraid this new feature doesn't work fine with Stacked Bars. This is a know issue already in the wish list to be implemented in future releases (TV52015085).
In the meanwhile you could modify the marks positions manually as here, or just draw the marks manually with custom drawing methods.
Best Regards,
![]() | Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) |
![]() ![]() ![]() ![]() ![]() ![]() |
Please read our Bug Fixing Policy |
-
- Newbie
- Posts: 23
- Joined: Tue Feb 10, 2009 12:00 am
Re: Centered Marks on Stacked Bars
Hi,
I am using version 8.08 with Delphi 2009. I can't find the MarksOnBar property, but since you say it's not optimal for stacked bars, I think I will go for the custom option.
I tried code like this:
I call this procedure after I create and populate all series and after the chart is drawn. For some reason, I still get a access violation (presumable because the marks position objects are not valid).
Alternatively, I may just draw them myself using the afterdraw event. Can i use the Marks.DrawItem method to draw them even if Marks.Visible = False ? Any suggestions how to calculate the center position of stacked bar values ?
I am using version 8.08 with Delphi 2009. I can't find the MarksOnBar property, but since you say it's not optimal for stacked bars, I think I will go for the custom option.
I tried code like this:
Code: Select all
procedure TFramePeriodicChart.RefreshMarks;
var
I,J: Integer;
S: TChartSeries;
begin
for I := 0 to Chart.SeriesCount - 1 do begin
S := Chart.Series[I];
if S.Visible and S.Active and S.Marks.Visible then begin
if S is TBarSeries then begin
for J := 0 to S.Marks.Positions.Count - 1 do begin
with S.Marks.Positions[J] do begin
Custom := True;
// calculate LeftTop.Y position
end;
end;
end;
end;
end;
end;
Alternatively, I may just draw them myself using the afterdraw event. Can i use the Marks.DrawItem method to draw them even if Marks.Visible = False ? Any suggestions how to calculate the center position of stacked bar values ?
Re: Centered Marks on Stacked Bars
Hello strobbeskoen,
I try your code and the access violation doesn't appear for me. Can you please, attached all project so we can try to reproduce your problem and find a solution for you?
Thanks,
I try your code and the access violation doesn't appear for me. Can you please, attached all project so we can try to reproduce your problem and find a solution for you?
Thanks,
Best Regards,
Sandra Pazos / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
![]() ![]() ![]() ![]() ![]() ![]() |
Instructions - How to post in this forum |
Re: Centered Marks on Stacked Bars
Hi,
I've just modified the sources to implement the request TV52015085. So the MarksOnBar will align the marks correctly also with Stacked bars in the next maintenance release.
Regarding the manually repositioning of the marks, I've tried the following code and it seems to work fine for me here, without access violations:
I've just modified the sources to implement the request TV52015085. So the MarksOnBar will align the marks correctly also with Stacked bars in the next maintenance release.
Regarding the manually repositioning of the marks, I've tried the following code and it seems to work fine for me here, without access violations:
Code: Select all
uses Series, Types;
procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
for i:=0 to 2 do
with Chart1.AddSeries(TBarSeries) as TBarSeries do
begin
FillSampleValues;
MultiBar:=mbStacked;
Marks.Arrow.Visible:=false;
Transparency:=20;
end;
RefreshMarks;
end;
procedure TForm1.RefreshMarks;
var
I,J: Integer;
S: TChartSeries;
barBounds: TRect;
barHeight: Integer;
begin
Chart1.Draw;
for I := 0 to Chart1.SeriesCount - 1 do begin
S := Chart1.Series[I];
if S.Visible and S.Active and S.Marks.Visible then begin
if S is TBarSeries then begin
for J := 0 to S.Marks.Positions.Count - 1 do begin
with S.Marks.Positions[J] do begin
Custom := True;
barBounds:=(S as TBarSeries).CalcBarBounds(J);
barHeight:=S.CalcYPosValue(0)-S.CalcYPosValue(S.YValue[J]);
LeftTop.Y:=barBounds.Top+(barHeight div 2);
LeftTop.X:=S.CalcXPos(J);
end;
end;
end;
end;
end;
end;
procedure TForm1.Chart1Scroll(Sender: TObject);
begin
RefreshMarks;
end;
procedure TForm1.Chart1Zoom(Sender: TObject);
begin
RefreshMarks;
end;
procedure TForm1.Chart1UndoZoom(Sender: TObject);
begin
RefreshMarks;
end;
Best Regards,
![]() | Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) |
![]() ![]() ![]() ![]() ![]() ![]() |
Please read our Bug Fixing Policy |
-
- Newbie
- Posts: 23
- Joined: Tue Feb 10, 2009 12:00 am
Re: Centered Marks on Stacked Bars
Hi,
I got a access violation because there are also null points so the mark position object can be nil.
I have a central procedure called RefreshChart. All the series are created at runtime depending on the settings the user selects.
The very first time when the form is created and the chart is refreshed, the marks still appeared in the old position so I added a Invalidate to refresh it.
After that, I used chart after draw and check for the flag if it's refreshed and then call RefreshMarks.
I also accounted for the height of the mark itself to position it.
Wouldn't barHeight always be the same as barBounds.Bottom - barBounds.Top ?
Seems to work okay now, apart from the shoehorn to refresh it the very first time.![Smile :)](./images/smilies/icon_smile.gif)
I got a access violation because there are also null points so the mark position object can be nil.
I have a central procedure called RefreshChart. All the series are created at runtime depending on the settings the user selects.
The very first time when the form is created and the chart is refreshed, the marks still appeared in the old position so I added a Invalidate to refresh it.
After that, I used chart after draw and check for the flag if it's refreshed and then call RefreshMarks.
I also accounted for the height of the mark itself to position it.
Wouldn't barHeight always be the same as barBounds.Bottom - barBounds.Top ?
Seems to work okay now, apart from the shoehorn to refresh it the very first time.
![Smile :)](./images/smilies/icon_smile.gif)
Code: Select all
procedure TFramePeriodicChart.RefreshChart;
begin
Inc(FRefreshing);
try
FRefreshed := False;
// create series and refresh other internal stuff ...
Chart.Draw;
RefreshMarks;
Chart.Invalidate;
FRefreshed := True;
finally
Dec(FRefreshing);
end;
end;
procedure TFramePeriodicChart.RefreshMarks;
var
I,J: Integer;
S: TChartSeries;
P: TSeriesMarkPosition;
barBounds: TRect;
barHeight: Integer;
// Y: Integer;
begin
for I := 0 to Chart.SeriesCount - 1 do begin
S := Chart.Series[I];
if S.Visible and S.Active and S.Marks.Visible then begin
if S is TBarSeries then begin
for J := 0 to S.Marks.Positions.Count - 1 do begin
P := S.Marks.Positions[J];
if P <> nil then begin
P.Custom := True;
barBounds := TBarSeries(S).CalcBarBounds(J);
barHeight := S.CalcYPosValue(0) - S.CalcYPosValue(S.YValue[J]);
P.LeftTop.Y := barBounds.Top + ((barHeight-P.Height) div 2);
// P.LeftTop.X := S.CalcXPos(J);
end;
end;
end;
end;
end;
end;
procedure TFramePeriodicChart.ChartAfterDraw(Sender: TObject);
begin
if FRefreshed then
RefreshMarks;
end;
- Attachments
-
- iqo2_cal2.gif (25.46 KiB) Viewed 11174 times
Re: Centered Marks on Stacked Bars
Hi,
I'm glad to hear it works fine for you now!![Very Happy :D](./images/smilies/icon_biggrin.gif)
Oups, you are right.strobbekoen wrote:Wouldn't barHeight always be the same as barBounds.Bottom - barBounds.Top ?
I'm glad to hear it works fine for you now!
![Very Happy :D](./images/smilies/icon_biggrin.gif)
Best Regards,
![]() | Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) |
![]() ![]() ![]() ![]() ![]() ![]() |
Please read our Bug Fixing Policy |