Page 1 of 1

Position of marks in self stacked bar chart

Posted: Fri Apr 15, 2005 11:54 am
by 8441509
Hi.

I need to add a self stacked horizontal bar chart that shows the spreading of data. This is basically the same as a pie chart, but this fits better into the UI.

The problem that I have is that the marks are positioned just on the stacked chart. Is there any way to position the marks beside the chart?

Best regards,

Joachim Marder

Posted: Fri Apr 15, 2005 1:21 pm
by narcis
Hi Joachim,

Yes, you can do something similar to:

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
  APosition:TSeriesMarkPosition;
begin
  Series1.FillSampleValues();
  Chart1.Draw();

  APosition:=TSeriesMarkPosition.Create;
  try
    for i:=0 to Series1.Count-1 do
    begin
      APosition.Custom:=True;
      APosition.LeftTop.X:=Series1.Marks.Positions[i].LeftTop.X;
      APosition.LeftTop.Y:=Series1.Marks.Positions[i].LeftTop.Y-35;
      Series1.Marks.Positions[i]:=APosition;
    end;
  finally
      APosition.Free;
  end;
end;

Posted: Wed Apr 20, 2005 5:07 pm
by 8441509
Dear Narcis.

I am using TeeChart Pro V6.01. If I use the code you posted, all marks in this series get transparent. Do you have any idea why?

And I wasn't able to find any documentation about the properties of TSeriesMarkPosition in the help file. Is this missing?

Best regards,

Joachim Marder

Posted: Thu Apr 21, 2005 9:20 am
by narcis
Hi Joachim,

Yes, you are right. Then you'd better use something similar to the code below not using TSeriesMarkPosition:

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  Series1.FillSampleValues();
  Chart1.Draw();

  for i:=0 to Series1.Count-1 do
  begin
    With Series1.Marks.Positions.Position[i] do
    Begin
      Custom:=True;
      LeftTop.Y := LeftTop.Y - 35;
    end;
  end;
  Series1.Marks.Arrow.Visible:=false;
  Series1.Repaint;
end;

Posted: Tue May 10, 2005 3:17 pm
by 8441509
Dear Narcis.

The solution you proposed is working quite OK. But The problem is that the call to the draw method makes the chart appear for a short time with the marks in their original position. This fklickering looks very odd.

Is there an alternative to the Draw() method that does fill the Marks.Positions property but does not update the chart on the screen?

Thanks and best regards,

Joachim

Posted: Wed May 11, 2005 1:46 pm
by Marjan
Hi, Joachim.

Series marks positions are created when chart is drawn. The only way around this is to manually create series marks positions as Narcis demonstrated in one of his previous posts. Alternatively, it might help enclosing the code in the Chart.AutoRepaint := False; and Chart.AutoRepaint := True, but I'm not 100% sure it will stop flickering:

Code: Select all

  Chart1.AutoRepaint := False;
  // your code comes here
  Chart1.AutoRepaint := True;

Posted: Mon Jun 06, 2005 8:27 am
by 8441509
Dear support team.

I spent hours and hours to get this simple task to work properly, but yet without success.
The only way around this is to manually create series marks positions as Narcis demonstrated in one of his previous posts.
If I do that, I need to not only fill in the postion, but also the Width, Height etc., because Marks.Positions is completely empty. But how should I know how many pixels my marks have to be wide and high? If I call TChart.Draw before, then there are default values that I can adjust, but then the chart flickers.
Alternatively, it might help enclosing the code in the Chart.AutoRepaint := False; and Chart.AutoRepaint := True, but I'm not 100% sure it will stop flickering
It won't stop flickering. The problem is that I need to call TChart.Draw to get the Marks.Positions filled with default values (see above). Is there any possibility to fill the Marks.Positions with default values without actually drawing the chart?

I am using a self stacked horizontal bar chart. The problem is that the mark of each segment is displayed right of this segment on top of the next segment. I find this very irritating because the user may think the mark he sees on a segment belongs to this segment, which is not true. So I just want to move the marks a little bit. A rather simply task I thought initially...

Are there any improvemnts in TeeChart V7 that would help me to solve this problem?

Best regards,

Joachim Marder
JAM Software

labeling points

Posted: Tue Nov 25, 2008 4:13 pm
by 10050941
I added a series1 using the editor so it exists at design time. I then set the onegetmark code to this

Code: Select all

procedure Tbubble1f.Series1GetMarkText(Sender: TChartSeries;
  ValueIndex: Integer; var MarkText: String);
var
  i: Integer;
  APosition:TSeriesMarkPosition;
begin
  Series1.FillSampleValues();
  Chart1.Draw();

  APosition:=TSeriesMarkPosition.Create;
  try
    for i:=0 to Series1.Count-1 do
    begin
      APosition.Custom:=True;
      APosition.LeftTop.X:=Series1.Marks.Positions[i].LeftTop.X;
      APosition.LeftTop.Y:=Series1.Marks.Positions[i].LeftTop.Y-35;
      Series1.Marks.Positions[i]:=APosition;
    end;
  finally
      APosition.Free;
  end;

end;
from the example. I has no impact. any ideas? thank you.

Posted: Tue Nov 25, 2008 4:30 pm
by narcis
Hi kualoa1,

Could you please send us a simple example project we can run "as-is" to reproduce the problem here?

You can either post your files at news://www.steema.net/steema.public.attachments newsgroup or at our upload page.

Thanks in advance.

labeling points

Posted: Tue Nov 25, 2008 6:56 pm
by 10050941
sending project snippet for as-is review too involved. uses components you do not have. i create series1a at design time. i set this series1a ongetmarktext code:

Code: Select all

procedure Tbubble1f.Series1aGetMarkText(Sender: TChartSeries;
  ValueIndex: Integer; var MarkText: String);
var
  i: Integer;
  APosition:TSeriesMarkPosition;
begin
//  Series1.FillSampleValues();
  Chart1.Draw();

  APosition:=TSeriesMarkPosition.Create;
  try
    for i:=0 to Series1.Count-1 do
    begin
      APosition.Custom:=True;
      APosition.LeftTop.X:=Series1.Marks.Positions[i].LeftTop.X;
      APosition.LeftTop.Y:=Series1.Marks.Positions[i].LeftTop.Y-35;
      Series1.Marks.Positions[i]:=APosition;
    end;
  finally
      APosition.Free;
  end;
end;

in my loop that draws the chart I have this code:

Code: Select all

 Series1:=TBubbleSeries.Create(self);
 Chart1.AddSeries(Series1);
--> Series1.OnGetMarkText:=Series1a.onGetMarkText;
but when I run this code it does not display chart and freezes.

it was workling without line marked -->

thoughts?

Posted: Wed Nov 26, 2008 8:37 am
by narcis
Hi kualoa1,

The problem here is that OnGetMarkText event is not designed for what you are using it and, moreover, you shouldn't call Chart1.Draw on it as you'll make your application fall in an endless loop.

Code below works fine for me here:

Code: Select all

Uses BubbleCh;

procedure TForm1.FormCreate(Sender: TObject);
var Series1 : TBubbleSeries;
    i       : Integer;
    x       : Double;
    y       : Double;
    radius  : Double;
begin
  Chart1.View3D:=false;
  Series1:=TBubbleSeries.Create(self);
  Chart1.AddSeries(Series1);

  Series1.Marks.Visible:=true;

  for i := 0 to 10 do
  begin
    x:=i;
    y:=random*10;
    radius:=random;
    Series1.AddBubble(x,y,radius);
  end;

  Chart1.Draw();
end;

procedure TForm1.Chart1AfterDraw(Sender: TObject);
var
  i: Integer;
  APosition:TSeriesMarkPosition;
begin

  APosition:=TSeriesMarkPosition.Create;
  try
    for i:=0 to Chart1[0].Count-1 do
    begin
      APosition.Custom:=True;
      APosition.LeftTop.X:=Chart1[0].Marks.Positions[i].LeftTop.X;
      APosition.LeftTop.Y:=Chart1[0].Marks.Positions[i].LeftTop.Y-35;
      Chart1[0].Marks.Positions[i]:=APosition;
    end;
  finally
      APosition.Free;
  end;
end;
OnGetMarkText event is for modifying marks text not its position.

labeling points

Posted: Wed Nov 26, 2008 11:41 am
by 10050941
thank you. I get this code to execute. however, the central purpose is to "wrap a long label". in your demo, you are not showing a label. when I tun this with a "long label" (eg 90 char), it still displays the full width.

Code: Select all

    lbl:=getcfield(b_labelfield1); 
    Series1.addbubble(x,y,radius,lbl);
lbl in above case can be 90 char; it still shows full with your afterdraw code.

thoughts?

Posted: Wed Nov 26, 2008 11:57 am
by narcis
Hi kualoa1,

Yes, as I already told you, my code is not parsing marks text. You should manually parse it using the OnGetMarkText event. You can use string provided by MarkText parameter, do the parsing you wish and then assign resulting string to MarkText again.

labeling points

Posted: Wed Nov 26, 2008 12:29 pm
by 10050941
thank you. i am close to giving up on this. a simple, common task has become an ordeal.

I keyed in on your recent note "The problem here is that OnGetMarkText event is not designed for what you are using it and, moreover, you shouldn't call Chart1.Draw on it as you'll make your application fall in an endless loop. " and therefore removed that code. I had set that code up in the manner that you had suggested before. now, i am totally adrift on this.

Posted: Wed Nov 26, 2008 2:28 pm
by narcis
Hi kualoa1,

Sorry if I haven't been clear enough.

In the case we have been speaking about, OnAfterDraw is better suited for setting custom position for marks. OnGetMarkText is for customizing the marks text itself, not its position.

I've arranged a simple example where every blank space in the marks is automatically replaced by a line break. In the same maner you should parse marks text to fit your needs.

Code: Select all

procedure TForm3.FormCreate(Sender: TObject);
var i: Integer;
begin
  for i := 0 to 10 do
    Series1.Add(random, 'Point number ' + IntToStr(i+1));
end;

procedure TForm3.Series1GetMarkText(Sender: TChartSeries; ValueIndex: Integer;
  var MarkText: string);
var tmp: Integer;
begin
  tmp:=pos(' ', MarkText);

  while tmp<>0 do
  begin
    MarkText:=copy(MarkText, 0, tmp-1) + #13 +
              copy(MarkText, tmp+1, Length(MarkText));
    tmp:=pos(' ', MarkText);
  end;
end;