Page 1 of 1

Displaying single marks

Posted: Mon Nov 08, 2010 3:10 pm
by 9342841
Hello,

With TeeChart 7.07 for Delphi6, I would like to display single mark on a LineSeries when, for exemple, I click on a Series point.
None of the Marks properties or methods (Marks.item[].visible, etc.) fit my needs until now.

An example of what I would like to do :
- I display a TLineSeries on a TChart (no Marks at that moment)
- I move the mouse over the Series and the nearest point is displayed, (using the NearestPoint Tool)
- I decide to click on a particular point, and a mark is displayed at that point.
- I can now move this mark (using the DragMarks tool).

I know how to use the NearestPoint and DragMarks Tools, but I don't find any convenient way to display single/custom/individual Marks...

Thanks for any advice,

Laurent

Re: Displaying single marks

Posted: Mon Nov 08, 2010 3:17 pm
by narcis
Hi Laurent,

What about using TMarksTipTool?

Re: Displaying single marks

Posted: Mon Nov 08, 2010 3:53 pm
by 9342841
Narcís wrote:Hi Laurent,
What about using TMarksTipTool?
Hi Narcis,

As I've seen of the TMarksTipTool behaviour, it won't fit my needs.
Here's a sample of a soft that really does exactly what I want :
CustomMarks.jpg
CustomMarks.jpg (15.33 KiB) Viewed 21031 times
The Marks are individually painted on the chart when the series point is clicked.

... and no, I don't have the source code of this soft :(
(... but I'm sure it uses TeeChart component !)

I've tried to use the series.marks.items.add method but failed because of lack of understanding the 'pointer' parameter...
By clicking on series points, I get their valueindex, but I don't know what to do with them to display the related marks (and only them !)

Laurent

Re: Displaying single marks

Posted: Mon Nov 08, 2010 4:00 pm
by narcis
Hi Laurent,

Ok, this is most likely done using TAnnotationTool object and its Callout object. You'll find examples at All Features\Welcome!\Tools\Annotation in the new features demo available at TeeChart's program group created by the binary installers. Besides moving annotation's callout you can also set annotations to custom positions as shown here. If you need to drag those tools you'd better use TRectangleTool instead of TAnnotationTool.

Hope this helps!

Re: Displaying single marks

Posted: Mon Nov 08, 2010 4:11 pm
by 9342841
Thanks Narcis.
I will try that and report, if it can help somebody else.

Regards,

Laurent

Re: Displaying single marks

Posted: Mon Nov 08, 2010 4:48 pm
by 9342841
Narcís wrote: Ok, this is most likely done using TAnnotationTool object and its Callout object. If you need to drag those tools you'd better use TRectangleTool instead of TAnnotationTool.
Hope this helps!
Narcis,
I've tried the TRectangleTool, but the object used in the sample enclosed above mostly behaves like a mark, and not like an Annotation.
Nevertheless, I'll try to go further in the Annotation direction, and also through the Series.Marks.Items.add().

Best,
Laurent

Re: Displaying single marks

Posted: Tue Nov 09, 2010 8:07 am
by narcis
Hi Laurent,
I've tried the TRectangleTool, but the object used in the sample enclosed above mostly behaves like a mark, and not like an Annotation.
In which sense? Which problems are you having with TRectangleTool?

Thanks in advance.

Re: Displaying single marks

Posted: Wed Nov 10, 2010 9:51 am
by 9342841
Hi Narcis,

I finally manage my individual 'marks' with the TRectangleTool.
I go deeper in this object's understanding and you were right : the sample I posted could be realized with this object.

To add a 'mark', I click on a serie point, create a TRectangleTool object and add it in a TObjectList.
All TRectangleTool properties (shape, callout, etc.) can be set to fit the way I wanted them to be displayed.

Thank you for your help,

Laurent

Re: Displaying single marks

Posted: Wed Nov 10, 2010 9:53 am
by narcis
Hi Laurent,

You're welcome. Thanks for your feedback. I'm glad to hear you could solve your problems.

Re: Displaying single marks

Posted: Wed Nov 17, 2010 4:37 pm
by 9342841
Hi Narcis,

Well, the RectangleTool is finally not so easy to use as a marks displayer.
It is not enough connected with the series points, and things like resizing the chart is tough to manage (the callout is connected to a screen point, not a serie point...)
Too complicated (and too much time consumer) to implement for me.

The Series.Marks would have definitively been the best object for my needs, but the lack of individual mark management is really a pity.
Is there an individual management of those Marks ?
What is the difference between the 'automatic' marks that are displayed with the Series.Marks.Visible property and the Marks that are added with the Series.Marks.Items.add(pointer) method ? (couldn't found what the pointer should be, anyway...)

Regards,

Laurent

Re: Displaying single marks

Posted: Fri Nov 19, 2010 3:14 pm
by yeray
Hi Laurent,
lolo1988 wrote:Well, the RectangleTool is finally not so easy to use as a marks displayer.
It is not enough connected with the series points, and things like resizing the chart is tough to manage (the callout is connected to a screen point, not a serie point...)
Too complicated (and too much time consumer) to implement for me.
Here you have an approach. You only have to recalculate the positions of the tools each time the chart is resized, zoomed, scrolled,... calling the same "recalc" method into all the events you want.

Code: Select all

  private
    { Private declarations }
    CustomMarks: array of TRectangleTool;
    procedure RecalcCustomMarksPositions;
//...
procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  Chart1.View3D:=false;

  Series1.FillSampleValues(10);
  Series1.Pointer.Visible:=true;

  SetLength(CustomMarks, Series1.Count);
  for i:=0 to Length(CustomMarks)-1 do
  begin
    CustomMarks[i]:=Chart1.Tools.Add(TRectangleTool) as TRectangleTool;
    with CustomMarks[i] do
    begin
      Text:=FloatToStr(Series1.YValue[i]);
      Shape.Width:=Canvas.TextWidth(CustomMarks[i].Text) + 10;
      Shape.Height:=Canvas.TextHeight(CustomMarks[i].Text) + 4;
      Callout.Arrow.Visible:=true;
    end;
  end;
end;

procedure TForm1.Series1ClickPointer(Sender: TCustomSeries; ValueIndex, X,
  Y: Integer);
begin
  CustomMarks[ValueIndex].Visible:=not CustomMarks[ValueIndex].Visible;
end;

procedure TForm1.RecalcCustomMarksPositions;
var i: Integer;
begin
  Chart1.Draw;

  for i:=0 to Series1.Count-1 do
  begin
    with CustomMarks[i] do
    begin
      Left:=Series1.CalcXPos(i) - Shape.Width div 2;
      Top:=Series1.CalcYPos(i) - 40;
      CustomMarks[i].Callout.XPosition:=Series1.CalcXPos(i);
      CustomMarks[i].Callout.YPosition:=Series1.CalcYPos(i);
    end;
  end;
end;

procedure TForm1.Chart1Zoom(Sender: TObject);
begin
  RecalcCustomMarksPositions;
end;

procedure TForm1.Chart1UndoZoom(Sender: TObject);
begin
  RecalcCustomMarksPositions;
end;

procedure TForm1.Chart1Scroll(Sender: TObject);
begin
  RecalcCustomMarksPositions;
end;

procedure TForm1.Chart1Resize(Sender: TObject);
begin
  RecalcCustomMarksPositions;
end;

Re: Displaying single marks

Posted: Tue Nov 23, 2010 12:40 pm
by 9342841
Hello Yeray,

I'll try this as soon as possible.
It finally seems not as complicated as I supposed it to be !

Thanks a lot,

Laurent

Re: Displaying single marks

Posted: Wed Nov 24, 2010 12:32 pm
by yeray
Hi Laurent,

If you have any problem with it, don't hesitate to let us know.

Re: Displaying single marks

Posted: Tue Jan 04, 2011 6:39 am
by 16558223
Hi Yeray,

I use C++ Builder for my projects. I have similar requirements of displaying markers as discussed here. I have tried to convert your code to C++ Builder, but no success. My difficulties are 1) I can not declare an array of TRectangleTool, 2) I could not assign a marker from TRectangleTool *marker, to a Chart by Chart->Tools->Add().

Could you show an equivalent code in C++Builder?

Thanks,
Shen

Re: Displaying single marks

Posted: Tue Jan 11, 2011 4:11 pm
by yeray
Hi Shen,

Excuse us for the delayed reply.
Here is the code in C++Builder. I've simplified it a little bit to use an static array for CustomMarks instead of the dynamic array in the delphi example.

Code: Select all

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  Chart1->View3D=false;

  Series1->FillSampleValues(10);
  Series1->Pointer->Visible=true;

  for(int i = 0; i < Series1->Count(); i++)
  {
	CustomMarks[i] = new TRectangleTool(Chart1);
	Chart1->Tools->Add(CustomMarks[i]);
	CustomMarks[i]->Text=FloatToStr(Series1->YValue[i]);
	CustomMarks[i]->Shape->Width=Canvas->TextWidth(CustomMarks[i]->Text) + 10;
	CustomMarks[i]->Shape->Height=Canvas->TextHeight(CustomMarks[i]->Text) + 4;
	CustomMarks[i]->Callout->Arrow->Visible=true;
  }

  Chart1->Draw();
  RecalcCustomMarksPositions();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Series1ClickPointer(TCustomSeries *Sender, int ValueIndex,
		  int X, int Y)
{
  CustomMarks[ValueIndex]->Visible=!CustomMarks[ValueIndex]->Visible;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RecalcCustomMarksPositions()
{
  Chart1->Repaint();

  int numValues = Series1->Count();
  for (int i=0; i<numValues; i++)
  {
	CustomMarks[i]->Left=Series1->CalcXPos(i) - CustomMarks[i]->Shape->Width / 2;
	CustomMarks[i]->Top=Series1->CalcYPos(i) - 40;
	CustomMarks[i]->Callout->XPosition=Series1->CalcXPos(i);
	CustomMarks[i]->Callout->YPosition=Series1->CalcYPos(i);
  }
}

void __fastcall TForm1::Chart1Zoom(TObject *Sender)
{
  RecalcCustomMarksPositions();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Chart1UndoZoom(TObject *Sender)
{
  RecalcCustomMarksPositions();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Chart1Scroll(TObject *Sender)
{
  RecalcCustomMarksPositions();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Chart1Resize(TObject *Sender)
{
  RecalcCustomMarksPositions();
}
//---------------------------------------------------------------------------