Recent

Author Topic: How to show time (by interval) on x axis?  (Read 524 times)

senglit

  • Jr. Member
  • **
  • Posts: 73
How to show time (by interval) on x axis?
« on: April 18, 2021, 10:46:07 am »
Hi all,

I got a Chart1 with a ListChartSource1 on my form. A timer is maintaining the data in ListChartSource1. The timer gets 1 value each second and adds it to ListChartSource1, and delete the first data of ListChartSource1, which means ListChartSource1 always has same amount of data(600 data for 10 min for example).

What I want to is to show the time on x axis by certain interval (30 secs for example), for if I show all of the labels on x axis, there will be some overlap. And if I set Chart1.Marks.OverlapPolicy to opHideNeighbour, it will show the time randomly. I want the time label show each 30 secs (for example, show the time at 08:15:00, 08:15:30, 08:16:00 ... don't show 08:15:03, 08:15:14...).

What I tried is:
1. set TChart.Marks.Source as ListChartSource1
2. Set Chart.BottomAxis.marks.style as smsLabel
2. Set Chart.BottomAxis.marks.OverlapPolicy as opIgnore
3. add value to ListChartSource1 like:
Code: Pascal  [Select][+][-]
  1. var
  2.   sec:integer;
  3.   TimeStr:string;    //format as "hh:mm:ss"
  4. begin
  5.   TimeStr:=GetTimeAsStr(rec.time);  //my own function, not lizarus function
  6.   sec:=SecondOf(rec.time);
  7.   if sec mod 30 <> 0 then TimeStr:='';
  8.   ListChartSource1.Add(rec.time,rec.value,TimeStr,myColor);
  9.   while ListChartSource1.Count>600 do ListChartSource1.Delete(0);
  10. end;
  11.  

I hope data with timestamp which is not 0 or 30 sec show empty label on x axis and others can show the time. But what I got is: some of the label can be shown correctly, but not all of them. 1 second later(new data comes), these labels disappeared and some other lables shows.

How to solve this problem? Thanks!
« Last Edit: April 18, 2021, 10:52:21 am by senglit »
I use Win10 + Lazarus 2.0.10 + FPC 3.2.0. All 64bit.

wp

  • Hero Member
  • *****
  • Posts: 8367
Re: How to show time (by interval) on x axis?
« Reply #1 on: April 18, 2021, 01:05:14 pm »
The easiest way to handle date/time values on the x axis is to add a TDateTimeChartSource to the chart and assign it to the Marks.Source of the BottomAxis (you must set Marks.Style = smsLabel, too). This chartsource is highly automized and adjusts its intervals to get "nice" labels for all zoom levels and chart sizes (well, mostly...). The key parameters to control the label selection are the MaxLength and MinLength settings of the Params property - this is the range in pixels in which the distance between axis marks is allowed to vary. Usually the defaults of these numbers are too small - I get much better results when I increase MaxLength to something like 125 and MinLength to 30. It is also a good idea to moderately increase the Tolerance which gives the labeller some freedom to select neighboring pixels when the label on the calculated mark position would have too many digits.

I know that you were requesting labels at half-minutes. In fact, I don't know if this can be achieved by the DateTimeChartSource. The way to go would probably be a separate ListChartSource which provides the labels at exactly these positions. But this also would require you to calculate label positions again and again since the axis labels can change with every data point added. Therefore, I'd ask you to look at my attached solution with TDateTimeChartSource, it results in nice labels over all chart sizes that I could achieve on my monitor. Although most of the work could be done in the Object Inspector, I did everything at runtime to be able to add lots of comments.

Ask again when the 30-sec labels are a key requirement, then I can try to create a solution with a ListChartSource.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

senglit

  • Jr. Member
  • **
  • Posts: 73
Re: How to show time (by interval) on x axis?
« Reply #2 on: April 19, 2021, 02:19:39 pm »
Thank you. It helps a lot. Right now the 30-sec is not a key requirement yet. I understand that many people get different requirement on TAChart. I wish it become better and better.

The easiest way to handle date/time values on the x axis is to add a TDateTimeChartSource to the chart and assign it to the Marks.Source of the BottomAxis (you must set Marks.Style = smsLabel, too). This chartsource is highly automized and adjusts its intervals to get "nice" labels for all zoom levels and chart sizes (well, mostly...). The key parameters to control the label selection are the MaxLength and MinLength settings of the Params property - this is the range in pixels in which the distance between axis marks is allowed to vary. Usually the defaults of these numbers are too small - I get much better results when I increase MaxLength to something like 125 and MinLength to 30. It is also a good idea to moderately increase the Tolerance which gives the labeller some freedom to select neighboring pixels when the label on the calculated mark position would have too many digits.

I know that you were requesting labels at half-minutes. In fact, I don't know if this can be achieved by the DateTimeChartSource. The way to go would probably be a separate ListChartSource which provides the labels at exactly these positions. But this also would require you to calculate label positions again and again since the axis labels can change with every data point added. Therefore, I'd ask you to look at my attached solution with TDateTimeChartSource, it results in nice labels over all chart sizes that I could achieve on my monitor. Although most of the work could be done in the Object Inspector, I did everything at runtime to be able to add lots of comments.

Ask again when the 30-sec labels are a key requirement, then I can try to create a solution with a ListChartSource.
I use Win10 + Lazarus 2.0.10 + FPC 3.2.0. All 64bit.

 

TinyPortal © 2005-2018