Android Question Some problems with xChart

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Using the latest B4A and xChart:
https://www.b4x.com/android/forum/threads/b4x-xui-xchart-class.91830/
and come across a few problems.

This is my code:

B4X:
Sub MakeBPChart
 Dim i As Int
 xChart1.ClearData
 xChart1.AddLine2("Systolic", xui.Color_Red, 2dip, "NONE", False, xui.Color_Red)
 xChart1.AddLine2("Diastolic", xui.Color_Blue, 2dip, "NONE", False, xui.Color_Blue)
 For i = CursorBP.RowCount - 1 To 0 Step - 1
  CursorBP.Position = i
  General.RunLog("MakeBPChart, CursorBP.GetInt2(0): " & CursorBP.GetInt2(0))
  General.RunLog("MakeBPChart, CursorBP.GetDouble2(1): " & CursorBP.GetDouble2(1))
  xChart1.AddLineMultiplePoints(General.ExcelDate2String(CursorBP.GetInt2(0), ""), _
           Array As Double(CursorBP.GetDouble2(1), CursorBP.GetDouble2(2)), _
           True)
 Next
 xChart1.ChartType = "LINE" 'still makes a bar chart!
 xChart1.AutomaticScale = True
 xChart1.XScaleTextOrientation = "VERTICAL"
 xChart1.YScaleMinValue = 0
 xChart1.Title = ""
 xChart1.XAxisName = ""
 xChart1.YAxisName = ""
 xChart1.DrawChart
 GotoPanel(ePanelType.Chart, False)
End Sub

1. xChart1.YScaleMinValue = 0 This doesn't seem to work, so I can't show the 0 on Y scale

2. xChart1.ChartType = "LINE" This didn't work, still made a Bar chart, but I think I have fixed this:

B4X:
Public Sub setChartType(ChartType As String)
'>>>> Altered <<<<
'If ChartType = "BAR" Or ChartType = "STACKED_BAR" Then
Graph.ChartType = ChartType
'End If
End Sub

3. When doing a long click in the chart the popup rectangle holding the points data is not wide enough, sothe longer text (in my case the x-axis text values) are cut short.

4. Not figured out yet how to make the x-axis points proportional to the size of the intervals.
Is this possible?

Otherwise it is very nice!

RBS
 

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Number One solved:
Should be xChart1.AutomaticScale = False
for xChart1.YScaleMinValue and xChart1.YScaleMaxValue to take effect.

RBS
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Thank you for the bug report.
1. xChart1.YScaleMinValue = 0 works only with xChart1.AutomaticScale = False
2. Amended
3. Amended
4. Not possible, the x values are strings not numbers.
Is it possible ? Yes, but it would need another chart type with x-axis values as numbers.

Please test the attached xChart.bas class.

upload_2018-5-12_11-55-52.png
 

Attachments

  • xChart.bas
    57.8 KB · Views: 244
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Thank you for the bug report.
1. xChart1.YScaleMinValue = 0 works only with xChart1.AutomaticScale = False
2. Amended
3. Amended
4. Not possible, the x values are strings not numbers.
Is it possible ? Yes, but it would need another chart type with x-axis values as numbers.

Please test the attached xChart.bas class.

View attachment 67785

Thanks, will test in a bit.
As to 4: How about add another optional argument to AddLineMultiplePoints that is an array with the x-axis values as numbers.
I know B4A doesn't do optional arguments, but you could do a Boolean property XAxisProportional and ignore the number array
if this is False.

Just found another little bug:
5. The Y-axis width for values can be too small if the max value has no decimals and the smaller values do have decimals.

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Thank you for the bug report.
1. xChart1.YScaleMinValue = 0 works only with xChart1.AutomaticScale = False
2. Amended
3. Amended
4. Not possible, the x values are strings not numbers.
Is it possible ? Yes, but it would need another chart type with x-axis values as numbers.

Please test the attached xChart.bas class.

View attachment 67785

Tested and all working fine now.

I solved number 5 without editing the xChart class (trying to avoid this) by adding a simple function
to get a sensible value for YScaleMaxValue:

B4X:
'iMin is the lowest value of the lower line and iMax is the highest value of the higher line
xChart1.YScaleMaxValue = GetNearestMultipleOfXInt(iMax + iMin / 2, 20, True)

B4X:
Sub GetNearestMultipleOfXInt(dVal As Double, iX As Int, bShowLowest As Boolean) As Int
 Dim iAbove As Long
 Do While iAbove < dVal
  iAbove = iAbove + iX
 Loop
 If bShowLowest Then
  Return iAbove - iX
 Else
  If iAbove - dVal < dVal - (iAbove - iX) Then
   Return iAbove
  Else
   Return iAbove - iX
  End If
 End If
End Sub


RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
What kind of scales do you have for the y axis?

Actually, doing AutomaticScale = True solves the problem. Only thing is that I can't then set the min and max value
of the Y-axis scale. AutomaticScale = True doesn't do a bad job of that though, but could do a bit better.

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Again, what kind of Y values do you have?
What do you expect?
Do you have examples?

These are blood pressure values with 2 lines, systolic and diastolic.
To give and example:
Systolic: 155,133,140,144,178,166,152
Diastolic: 72,86,80,77,87,80,69

RBS
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
This is what I get:

upload_2018-5-14_8-16-24.png


With the code below:

B4X:
LineChart2.AutomaticScale = False
LineChart2.YScaleMinValue = 0
LineChart2.YScaleMaxValue = 200
LineChart2.Title = "Blood pressure"
LineChart2.YAxisName = "Pressure"
LineChart2.XAxisName = "Day"
LineChart2.XScaleTextOrientation = "VERTICAL"

LineChart2.ClearData
LineChart2.AddLine("Systolic", xui.Color_Red)
LineChart2.AddLine("Diastolic", xui.Color_Blue)

LineChart2.AddLineMultiplePoints("2018.02.10", Array As Double(155, 72), True)
LineChart2.AddLineMultiplePoints("2018.02.11", Array As Double(133, 86), True)
LineChart2.AddLineMultiplePoints("2018.02.12", Array As Double(140, 80), True)
LineChart2.AddLineMultiplePoints("2018.02.13", Array As Double(144, 77), True)
LineChart2.AddLineMultiplePoints("2018.02.14", Array As Double(178, 87), True)
LineChart2.AddLineMultiplePoints("2018.02.15", Array As Double(166, 80), True)
LineChart2.AddLineMultiplePoints("2018.02.16", Array As Double(152, 69), True)

LineChart2.DrawChart

Note, that you can also set all these properties directly in the Designer.

You cannot combine AutomaticScale with manuel scale settings.



C:\Users\klaus\AppData\Local\Temp\SNAGHTML16f7851a.PNG
 
Last edited:
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
This is what I get:

View attachment 67858

With the code below:

B4X:
LineChart2.AutomaticScale = False
LineChart2.YScaleMinValue = 0
LineChart2.YScaleMaxValue = 200
LineChart2.Title = "Blood pressure"
LineChart2.YAxisName = "Pressure"
LineChart2.XAxisName = "Day"
LineChart2.XScaleTextOrientation = "VERTICAL"

LineChart2.ClearData
LineChart2.AddLine("Systolic", xui.Color_Red)
LineChart2.AddLine("Diastolic", xui.Color_Blue)

LineChart2.AddLineMultiplePoints("2018.02.10", Array As Double(155, 72), True)
LineChart2.AddLineMultiplePoints("2018.02.11", Array As Double(133, 86), True)
LineChart2.AddLineMultiplePoints("2018.02.12", Array As Double(140, 80), True)
LineChart2.AddLineMultiplePoints("2018.02.13", Array As Double(144, 77), True)
LineChart2.AddLineMultiplePoints("2018.02.14", Array As Double(178, 87), True)
LineChart2.AddLineMultiplePoints("2018.02.15", Array As Double(166, 80), True)
LineChart2.AddLineMultiplePoints("2018.02.16", Array As Double(152, 69), True)

LineChart2.DrawChart

Note, that you can also set all these properties directly in the Designer.

You cannot combine AutomaticScale with manuel scale settings.



C:\Users\klaus\AppData\Local\Temp\SNAGHTML16f7851a.PNG
Yes, that works fine. Actually it is better for this particular chart to have fixed values for YScaleMinValue and YScaleMaxValue
as it easier for the user to see quickly what is going on.
I needed to add some code to avoid getting the dates on the x-axis getting too close together.
In case somebody finds that useful, this is my code:

B4X:
Sub ShowBPChart
 
 Dim i As Int
 Dim iMod As Int
 Dim iRows As Int
 Dim bAllXAxisMarks As Boolean
 
 If CursorBP.RowCount < 2 Then
  Return 'can't make a chart
 End If

 xChartBP.ClearData
 xChartBP.AddLine("Systolic", xui.Color_Red)
 xChartBP.AddLine("Diastolic", xui.Color_Blue)
 
 iRows = CursorBP.RowCount
 
 If iRows < 30 Then
  bAllXAxisMarks = True
 Else
  iMod = iRows / 16
 End If
 
 If bAllXAxisMarks Then
  For i = iRows -1 To 0 Step - 1
   CursorBP.Position = i
   xChartBP.AddLineMultiplePoints(General.ExcelDate2String(CursorBP.GetInt2(0), ""), _
           Array As Double(CursorBP.GetInt2(1), CursorBP.GetInt2(2)), _
              bShowXAxisValues)
  Next
 Else
  For i = iRows - 1 To 0 Step - 1
   CursorBP.Position = i
   'so we always show the first date, but not the second as it may get too close to the first
   '>>>>this needs some further work second shown date can still get too close to first
   '-----------------------------------------------------------------------------------------
   xChartBP.AddLineMultiplePoints(General.ExcelDate2String(CursorBP.GetInt2(0), ""), _
           Array As Double(CursorBP.GetInt2(1), CursorBP.GetInt2(2)), _
           (i = iRows - 1 Or i Mod iMod = 0) And bShowXAxisValues And i <> iRows - 2)  
  Next
 End If
 
 xChartBP.ChartType = "LINE"
 xChartBP.AutomaticScale = False 'needs to be False for YScaleMaxValue and YScaleMinValue to take effect
 xChartBP.XScaleTextOrientation = "VERTICAL"
 xChartBP.IncludeLegend = "TOP_RIGHT"  'not really needed
 xChartBP.YScaleMaxValue = 260
 xChartBP.YScaleMinValue = 0
 xChartBP.Title = "BP"
 xChartBP.XAxisName = ""
 xChartBP.YAxisName = ""
 xChartBP.DrawChart
 
 lblPatChartBP.Text  = lblPatBP.Text
 
 GotoPanel(ePanelType.ChartBP, False)
 
End Sub


Great work this xChart class!


RBS
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Can you please test the class below.
I added a new property: YZeroAxis, which is set to true by default.
You will see the difference by commenting or uncommenting this line:
LineChart2.YZeroAxis = False in the CreateLineChart2Data routine.
This sets the min Y scale to zero if all values are >= 0.
and sets the max Y scale to zero if all values are <= 0.
Another change is for the different color properties, the given values must be xui.Color values and not product native values.
Example: LineChart2.ValuesTextColor = xui.Color_Red instead of LineChart2.ValuesTextColor = Colors.Red for BaA.
 

Attachments

  • xChart_V1_5.zip
    32 KB · Views: 239
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Can you please test the class below.
I added a new property: YZeroAxis, which is set to true by default.
You will see the difference by commenting or uncommenting this line:
LineChart2.YZeroAxis = False in the CreateLineChart2Data routine.
This sets the min Y scale to zero if all values are >= 0.
and sets the max Y scale to zero if all values are <= 0.
Another change is for the different color properties, the given values must be xui.Color values and not product native values.
Example: LineChart2.ValuesTextColor = xui.Color_Red instead of LineChart2.ValuesTextColor = Colors.Red for BaA.

Tested and works fine.
I had to fix a bug in the Designer property of YZeroAxis:
There was a comma in the description part, should be:
#DesignerProperty: Key: YZeroAxis, DisplayName: Y zero axis, FieldType: Boolean, DefaultValue: True, Description: Sets the min value to 0 if all values are > 0 and max valule to 0 if all values are < 0

I think there still may be a problem with the width (being to small) of the Y-axis, if the highest value has no decimals and lower value do have decimals.
Will check in a bit.

RBS
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Tested and works fine.
I had to fix a bug in the Designer property of YZeroAxis:
There was a comma in the description part, should be:
#DesignerProperty: Key: YZeroAxis, DisplayName: Y zero axis, FieldType: Boolean, DefaultValue: True, Description: Sets the min value to 0 if all values are > 0 and max valule to 0 if all values are < 0

I think there still may be a problem with the width (being to small) of the Y-axis, if the highest value has no decimals and lower value do have decimals.
Will check in a bit.

RBS

Tested and width of Y-axis seems fine now in the mentioned situation.

RBS
 
Upvote 0
Top