Sorry, I don't quite understand what the issue is and how your code relates to the screenshots shown. They just look as if the y values are screwed up.
Have a look at
wiki.lazarus.freepascal.org/TAChart_documentation for some documentation of TAChart in general and the box/whisker series in particular.
Generally, when working with Box-Whisker-Series I'd prefer the AddXY overload with the many parameters (your second code snippet) since it is clear which parameter means what:
function TBoxAndWhiskerSeries.AddXY( AX, AYLoWhisker, AYLoBox, AY, AYHiBox, AYHiWhisker: Double;
AXLabel: String = ''; AColor: TColor = clTAColor): Integer; In addition this method uses the correct YCount value of the ChartSource now (you have to use Lazarus trunk to get that feature, otherwise you have to set YCount to 5 manually before populating the series - see also below).
The shorter method with the YList is more complicated because the YList is to be counted in addition to the ordinary Y value provided as the second parameter of the AddXY call. Therefore YCount is equal to the length of the YList plus 1 (for the ordinary Y), and Y[0] = LoWhisker is Y, Y[1]=YLoBox is YList[0], etc. Therefore, your first code snipped is not correct since it screws up the Y values. That's the way it should be (with some optimizations as explained below):
var
ylist: array[0..3] of double;
...
chart2boxandwhiskerseries1.ListSource.YCount = 5; // Prepare space for 5 y values
chart2boxandwhiskerseries1.ListSource.BeginUpdate;
dm1.tblroughdist.DisableControls;
try
while not dm1.tblroughdist.eof do
begin
ylist[0] := dm1.tblroughdist.FieldByName('p10').value; // Y[1] = lower bound of box --> see doc!
ylist[1] := dm1.tblroughdist.FieldByName('p50').value; // Y[2] = medium line
ylist[2] := dm1.tblroughdist.FieldByName('p90').value; // Y[3] = upper bound of box
ylist[3] := dm1.tblroughdist.FieldByName('p_high').value; //Y[4] = upper whisker
chart2boxandwhiskerseries1.AddXY(
dm1.tblroughdist.FieldByName('surveyyear').value, //AX
dm1.tblroughdist.FieldByName('p_low').value, // Y[0] = lower whisker
ylist);
dm1.tblroughdist.next;
end;
finally
dm1.tblroughdist.EnableControls;
chart2boxandwhisherseries1.ListSource.EndUpdate;
end;
There is no need to call Chart.Repaint explicitly, this is done automatically whenever data points are added. Conversely, I'd recommend to turn off repainting while the series is populated because it can slow down the program. This can be done by calling "BeginUpdate"/"EndUpdate" of the ChartSource before/after populating, just like shown above - if you add data by calling AddXY of the series then the ChartSource can be accessed by the ListSource of the series.
Another optimization is the database access which you are using. If the table that you want to plot is linked to data-sensitive controls like a DBGrid it is highly recommended to disable updating the visual controls while you are looping through all records for building the series. This is done by calling "DisableControls"/"EnableControls" of the dataset.