B4A Library MPAndroidCharts - Various type of graphs / charts (Latest library V1.22 in post #1)

Edit 6 Sep 2015: Post #3 adds Single Vertical Bar Charts and update for Pie Charts
Edit 8 Sep 2015 Post #6 update for Single Vertical Bar Charts
Edit 11 Sep 2015 Post #7 adds Single Line Charts
Edit 12 Sep 2015 Post #8 update for Single Line Charts
Edit 12 Sep 2015 Post #9 adds Single Horizontal Bar Charts
Edit 12 Sep 2015 Post #11 adds Radar Charts
Edit 13 Sep 2015 Post #12 update for Single Line and Single Bar Charts
Edit 14 Sep 2015 Post #16 update for Radar Charts
Edit 16 Sep 2015 Post #19 adds Multiple Line Charts
Edit 17 Sep2016 Post #21 adds Multi Vertical Bar Charts
Edit 19 Sep 2015 Post #23 adds Multi Bubble Charts
Edit 19 Sep 2015 Post #24 adds Multi Horizontal Bar Charts
Edit 19 Sep 2015 Post #25 adds Multi Scatter Charts
Edit 19 Sep 2015 Post #26 adds Stacked Bar Charts
Edit 20 Sep 2015 Post #27 adds Candlestick Charts
Edit 20 Sep 2015 Post #28 adds Combined Line & Bar Charts
Edit 23 Sep 2015 Post #31 fixed no-show of Chart Title for Combined Charts and added ability to rotate X-axis labels between -30 and + 30 degrees

I am busy wrapping this Github project. Attached is the Pie Chart functionality of the project/library. Posting the B4A project and Library files. Copy the library files to your additional library folder.

Some remarks about the Pie Chart:
1. It will display the values passed as a percentage of the total of the values that you pass
2. There are 3 x arrays that are passed to the library. Ensure that you pass the same number of elements in each of the arrays.
3. When you click on a pie slice the slice will increase in radial size (see pics below)
4. If you click on the radial increased slice it will return to normal size.
5. You can spin the pie chart around its centre point (CW and ACW) with your finger.

Untouched ...

Pie.gif


1.png


Green slice touched ...

2.png


Pie Chart rotated with finger...

3.png



Some sample code:

B4X:
#Region  Project Attributes
    #ApplicationLabel: MPChart
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: landscape
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private mpc1 As PieChart
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")

mpc1.DrawHoleEnabled = True
mpc1.HoleColorTransparent = True

mpc1.TransparentCircleColor = Colors.White
mpc1.TransparentCircleAlpha = 110

mpc1.HoleRadius = 58.0
mpc1.TransparentCircleRadius = 61.0

mpc1.DrawCenterText = True

mpc1.CenterText = "Wrapped by Johan"
mpc1.CenterTextColor = Colors.White
mpc1.CenterTextRadiusPercent = 100.0
mpc1.CenterTextSize = 15.0

mpc1.DrawSliceText = True
mpc1.HoleColor = Colors.Black
mpc1.TransparentCircleColor = Colors.Transparent

mpc1.setTheLegendPosition
mpc1.TheLegendColor = Colors.yellow
mpc1.TheLegendTextSize = 12.0
mpc1.LegendTitle = "MONTHS"

mpc1.ChartDescription = "TITLE : Some Arbitrary Data"
mpc1.ChartDescriptionColor = Colors.ARGB(200,0,255,255)
mpc1.ChartDescriptionTextSize = 17

mpc1.ValueTextColor = Colors.Black
mpc1.ValueTextSize = 15.0

mpc1.PieColors = Array As Int(Colors.Blue, Colors.Yellow, Colors.Green, Colors.Red, Colors.Magenta, Colors.Cyan)
mpc1.LegendText = Array As String("Jan", "Feb", "Mar", "Apr", "May", "Jun")
mpc1.ChartData = Array As Float(128.0, 16.0, 46.0, 40.0, 30.0, 40.0)    'values - it will be converted to %

mpc1.PieData = 6

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
 

Attachments

  • b4aMPChart.zip
    7.9 KB · Views: 1,408
  • mpChartLibraryFiles.zip
    221.5 KB · Views: 1,494
  • mpChartLibV1.15.zip
    355.2 KB · Views: 608
  • mpChartLibV1.16.zip
    355.7 KB · Views: 607
  • mpChartLibV1.17.zip
    355.8 KB · Views: 775
  • mpChartLibV1.18.zip
    356.4 KB · Views: 685
  • mpChartLibV1.20.zip
    358.1 KB · Views: 467
  • mpChartLibV1.21.zip
    358 KB · Views: 41
  • mpChartLibV1.22.zip
    359.2 KB · Views: 66
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
Hi Johan,
I'm using mpChart v1.01 with B4A 5.80 and I'm having a bit of an issue with right Y axis labels on a MultiLineChart. I originally posted the issue in the Android Questions forum a few days ago and user mc73 guided me here to post it as a possible bug report.

The issue appears or disappears depending on the left hand Y axis values. I've stripped out most of the code from my app which isn't relevent and attached the zipped up project as well as some screenshots showing the issue. The first screenshot looks as I'd expect but the second one looks as though the right hand Y axis values have been rounded to the nearest integer.

To explain the charts: There are five sets of data on each chart, 4 of them are tied to the left hand Y axis and the fifth (cyan dashed) is tied to the right hand Y axis. The only difference between the two sets of data is in the values behind the lines tied to the left hand Y axis, the data behind the right side Y axis is the same in both cases. You'll see that the right Y axis values shown are: 0.00, 0.60, 1.20, 1.80, 2.40, 3.00 in the first screenshot and 0, 1, 1, 2, 2, 3 in the second screenshot.

I'm leaving the Y axes limits to be automatically set.
Somehow the right hand Y axis label values are being influenced by the left hand Y axis values.

View attachment 42249 View attachment 42250

Since my original post I've made some changes to see if I could narrow down the problem. I've added the following to see what affect it had:

chrtChart.YaxisLeftMinVal = 0
chrtChart.YaxisLeftMaxVal = 300

chrtChart.YaxisRightMinVal = 0
chrtChart.YaxisRightMaxVal = 3

The results are shown in the following screenshots (using the same underlying data as before):

View attachment 42252 View attachment 42253

As you can see, the 1st image looks just fine. Obviously 4 of the lines are squashed right down the bottom but that's to be expected having set the left Y axis limits to the chosen values. The 2nd image is still showing the same (original) issue. So it looks as though the issue is related to the actual (left hand) graphed values and not the left Y axis limits. I've also noticed that the left Y axis labels in the 2nd image have been formatted with no decimals even though the axis limits haven't changed. What I'm guessing from this is that both sets of Y axis labels are being rounded to the nearest integer somehow.

Hopefully you'll get some time to take a look at this and that I've managed to narrow down where the problem might be.
Any help would be greatly appreciated.

I've attached the zipped project (modified since original post in other subforum). If you need me to do anything else just let me know.

Many thanks
Marcus
If I change your code so that the same graph (in this case data from Readings2) is drawn on both tabs:
B4X:
    DrawChart("Readings2", mlc1)
    DrawChart("Readings2", mlc2)

3.png


4.png


...then the Y-axis labels of the graphs on both tabs appear the same - in this case without any decimal points.

If I change the code to:
B4X:
    DrawChart("Readings1", mlc1)
    DrawChart("Readings1", mlc2)
...then the Y-axis labels of the graphs on both tabs also appear the same - in this case with decimal points.

1.png


2.png


I can't see in the library any reason why they should be different. Are you passing the same type of values to both graphs? The graphs expect type float as the data. Could it be something related to the data that you pass?
 

beaker

Member
Licensed User
The 'Readings2' table is a copy of 'Readings1' with the data in columns 2, 3 & 4 multiplied by a factor of 38.66976 and column 5 multiplied by a factor of 88.57396. The data in Columns 1 & 6 are the same in both tables and the datatypes are the same in both tables.

In fact in my 'real' app there is only one table and the values depend on which units have been selected by the user. I only created this stripped down version with two tables to make the code simpler and hopefully easier for someone else to look through and track down the problem.

I've attempted to simplify things further and I've attached another version which doesn't get its data from a db table. Instead, the values are set in the code and I've chosen values similar to those in the original tables. There are also only three data points. Hopefully this will make it a bit easier to see what's going on. I've commented out the lines that set the maximum Y axis values so that the charts autoscale but the issue is present whether autoscaling is on or off.

Thanks for your time, it's greatly appreciated.
 

Attachments

  • MLC Y Axis Labels Issue non DB.zip
    33.2 KB · Views: 216

Johan Schoeman

Expert
Licensed User
Longtime User
Do you think it could be related to this issue?:
https://github.com/PhilJay/MPAndroidChart/issues/1497

I realise it's a different chart type but if they use some common code then maybe...?
I will have to dig into the code of the original Github project to see if I can track down the problem. The wrapper merely passes on the values from B4A to the original project to draw the graph with. Will see if I can find it.

The issue in your post above relates to the values that is displayed above the bars in the barchart. The problem you have must sit in the class that handles the Y-axis.
 

Johan Schoeman

Expert
Licensed User
Longtime User
The 'Readings2' table is a copy of 'Readings1' with the data in columns 2, 3 & 4 multiplied by a factor of 38.66976 and column 5 multiplied by a factor of 88.57396. The data in Columns 1 & 6 are the same in both tables and the datatypes are the same in both tables.

In fact in my 'real' app there is only one table and the values depend on which units have been selected by the user. I only created this stripped down version with two tables to make the code simpler and hopefully easier for someone else to look through and track down the problem.

I've attempted to simplify things further and I've attached another version which doesn't get its data from a db table. Instead, the values are set in the code and I've chosen values similar to those in the original tables. There are also only three data points. Hopefully this will make it a bit easier to see what's going on. I've commented out the lines that set the maximum Y axis values so that the charts autoscale but the issue is present whether autoscaling is on or off.

Thanks for your time, it's greatly appreciated.
From the Yaxis class...

/**
* Sets the formatter to be used for formatting the axis labels. If no formatter is set, the chart will
* automatically determine a reasonable formatting (concerning decimals) for all the values that are drawn inside
* the chart. Use chart.getDefaultValueFormatter() to use the formatter calculated by the chart.
*
* @param f
*/

I will add a formatter for the Y axis and post an updated library
 

beaker

Member
Licensed User
Ah yes, that looks like it's the culprit :)
While you're at it you couldn't take a look at the formatting for the markers could you? At the moment the decimal seperator is a comma and I can't see a way of changing this to a decimal point.
 

Johan Schoeman

Expert
Licensed User
Longtime User
Ah yes, that looks like it's the culprit :)
While you're at it you couldn't take a look at the formatting for the markers could you? At the moment the decimal seperator is a comma and I can't see a way of changing this to a decimal point.
It shows decimal points on my devices - see various posting in this thread with pics showing a point. Don't know why yours is showing a comma. It must have something to do with the setup of your device (locale). I have seen this before with something that @BlueVision was doing. I was seeing a point and he was seeing a comma. Seems like everything changes once you cross the equator.....;)
 

beaker

Member
Licensed User
Ok, I'm in the UK so it should be a point.

I've knocked up a quick project (using some code found here on the B4A forum) to get the decimal seperator character from the system and it's returning a point and not a comma. I've also not come across any other instances where I get a comma instead of a point so I'm a bit confused at the moment :confused:

I've attached the project so you can see how I've gone about retrieving the decimal seperator character from the system.

Here's a screenshot showing it running on my HTC One M8:
Screenshot.png
 

Attachments

  • GetDecimalSeperator.zip
    7.7 KB · Views: 179

Johan Schoeman

Expert
Licensed User
Longtime User
Ah yes, that looks like it's the culprit :)
While you're at it you couldn't take a look at the formatting for the markers could you? At the moment the decimal seperator is a comma and I can't see a way of changing this to a decimal point.
New library files attached that sorts out the number of digits after the decimal point for the left and right Y-axis. Use it in your B4A code as follows:

B4X:
chrtChart.YaxisLeftNumberOfDigits = 1
chrtChart.YaxisRightNumberOfDigits = 3


5.png
 

Attachments

  • mpChartLib11Mar2016.zip
    353.6 KB · Views: 321
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
That's great, thanks very much Johan. I'll give that a go. :)
No need to thank me - just click on Like if it works. Or better, just donate GBP 100 000-00....:)
 

phukol

Active Member
Licensed User
Longtime User
hi guys im using this sub to generate data for my radarchart
B4X:
Sub loadRadar( strScore() As Float, strTitle As String,strCat() As String,intCount As Int)
    rc1.ChartDescription = strTitle
    rc1.ChartDescriptionColor = Colors.RGB(33,33,33)
    rc1.ChartDescriptionTextSize = 12  
    rc1.Width = pnl1.Width
    rc1.Height = pnl1.Height

    rc1.LegendShapeSize = 15.0
    rc1.setTheLegendPositionAndForm("BELOW_CHART_CENTER","CIRCLE")
    rc1.TheLegendColor = Colors.yellow
    rc1.TheLegendTextSize = 10.0  

    rc1.ValueTextColor =  Colors.RGB(33,33,33)
    rc1.ValueTextSize = 12.0
    rc1.YaxisTextSize = 10.0
    rc1.YaxisTextColor = Colors.RGB(33,33,33)
  
    rc1.Chart_1_Data = strScore
    rc1.XaxisTextColor = Colors.Cyan
    rc1.XaxisTextSize = 12.0
  
    rc1.ValueTextSize = 10.0
    rc1.ValueTextColor = Colors.Yellow  
    rc1.DrawGraphValues = False  
    rc1.GraphLineColor = Array As Int(Colors.Yellow, Colors.Red, Colors.Blue, Colors.Green, Colors.Cyan)
    rc1.GraphLineWidth = 2.0
    rc1.DrawFilled = True
  
    rc1.WebConcentricColor = Colors.Green
    rc1.WebRadialColor = Colors.Red
    rc1.WebAlpha = 200
    rc1.ConcentricLineWidth = 1.5
    rc1.RadialLineWidth = 2
    rc1.DrawWeb = True
  
    rc1.XaxisLables =  strCat

    rc1.MarkerToUse = 4
    rc1.setRadarData(1,8)
End Sub

however im encountering this error:
B4X:
java.lang.NullPointerException
    at mpandroidchartwrapper.radarChartWrapper.setRadarData(radarChartWrapper.java:302)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:747)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:342)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:157)
    at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:267)
    at ed.reviewamigo.progress._loadradar(progress.java:1124)
    at ed.reviewamigo.progress._filltable(progress.java:695)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:702)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:339)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
    at ed.reviewamigo.progress.afterFirstLayout(progress.java:102)
    at ed.reviewamigo.progress.access$000(progress.java:17)
    at ed.reviewamigo.progress$WaitForLayout.run(progress.java:80)
    at android.os.Handler.handleCallback(Handler.java:725)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5041)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    at dalvik.system.NativeStart.main(Native Method)
 

Johan Schoeman

Expert
Licensed User
Longtime User
hi guys im using this sub to generate data for my radarchart

however im encountering this error:
B4X:
java.lang.NullPointerException
    at mpandroidchartwrapper.radarChartWrapper.setRadarData(radarChartWrapper.java:302)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:747)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:342)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:157)
    at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:267)
    at ed.reviewamigo.progress._loadradar(progress.java:1124)
    at ed.reviewamigo.progress._filltable(progress.java:695)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:702)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:339)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
    at ed.reviewamigo.progress.afterFirstLayout(progress.java:102)
    at ed.reviewamigo.progress.access$000(progress.java:17)
    at ed.reviewamigo.progress$WaitForLayout.run(progress.java:80)
    at android.os.Handler.handleCallback(Handler.java:725)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5041)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    at dalvik.system.NativeStart.main(Native Method)

I think it might be looking for the legend text. If you don't want to display the legend text then pass something like this:
B4X:
mrc1.LegendText = Array As String("", "", "", "", "")

It obviously depends on how many charts you want to display - my above code extract assumes 5 radar charts to be displayed. You have set all the below for the legend but not the legend text.....?
B4X:
    rc1.LegendShapeSize = 15.0
    rc1.setTheLegendPositionAndForm("BELOW_CHART_CENTER","CIRCLE")
    rc1.TheLegendColor = Colors.yellow
    rc1.TheLegendTextSize = 10.0
 

dusanpon

New Member
Licensed User
Longtime User
Hi,

First I would like to congratulate and thank you, Johan, on the great work with graphs.

Then I state my problem which is causing me troubles for two days already. I am a new user not knowing much about b4a, and I would like to use the graph. I can run the original example from Johan, and I can modify the example to do my work. Everything is fine here as long as I use the original software and modify it. However, when I start by writing my own program from scratch ("File" -> "New" + enable libraries from post 149) and using a copy of the source code from the Johans's original example, the thing does not work. All I get is an error message about resources not found; the line causing the error is "MultiLineChart1.SetLineData(2,50)".

I checked the forum and did not find any complains of this kind, therefore it must be my error. It looks to me as if something is not declared correctly in my version of the software, but declared correctly in the original software. Where to look for? Also: I am comming from a region with modified character set: decimal sign is a comma, not a dot, and alike. Could this be a problem?
Thanks in advance

Dušan, Slovenia
 

JNG

Member
Licensed User
Hi,

I am unable to configure Charts in my project and getting the following error pl advise

regards
 

Attachments

  • error.txt
    23.9 KB · Views: 168

Johan Schoeman

Expert
Licensed User
Longtime User
Hi,

First I would like to congratulate and thank you, Johan, on the great work with graphs.

Then I state my problem which is causing me troubles for two days already. I am a new user not knowing much about b4a, and I would like to use the graph. I can run the original example from Johan, and I can modify the example to do my work. Everything is fine here as long as I use the original software and modify it. However, when I start by writing my own program from scratch ("File" -> "New" + enable libraries from post 149) and using a copy of the source code from the Johans's original example, the thing does not work. All I get is an error message about resources not found; the line causing the error is "MultiLineChart1.SetLineData(2,50)".

I checked the forum and did not find any complains of this kind, therefore it must be my error. It looks to me as if something is not declared correctly in my version of the software, but declared correctly in the original software. Where to look for? Also: I am comming from a region with modified character set: decimal sign is a comma, not a dot, and alike. Could this be a problem?
Thanks in advance

Dušan, Slovenia
Look in the /Objects/res/drawable folder of this project https://www.b4x.com/android/forum/t...ry-files-in-post-149.58017/page-7#post-391641

There are files that you are missing from your project when you started a new project. Copy the files to your new project's /Objects/res/drawable folder and make sure once copied that you set them to READ ONLY before you compile your B4A project.
 

dusanpon

New Member
Licensed User
Longtime User
Look in the /Objects/res/drawable folder of this project https://www.b4x.com/android/forum/t...ry-files-in-post-149.58017/page-7#post-391641

There are files that you are missing from your project when you started a new project. Copy the files to your new project's /Objects/res/drawable folder and make sure once copied that you set them to READ ONLY before you compile your B4A project.

Thanks, but I had those files copied already.
I have tried once more to run your example from the post, and your example works fine. Then I created a new file and copied the complete source (lines 1 to including 225) from your example into the newly created file thus erasing the initial content of the newly created file. Then I copied the files from "drawable" folder into the corresponding place in the newly created project, made sure that they are "read-only" and activated the same libraries as are active in your example. No other changes were made.
Compiling of the newly created program works fine, no error messages there. There is, however, a warning message "Variable 'mlc1' was not initialized", this I have just noticed. Then the program starts on Samsung P6800, and crashes with the message: "Error occured on line 167 (Main)" and "Resources not found exception...."
I apologize for such stupid problems of mine, but no start is simple. Thanks for your help.
Regards

Dušan
 
Top