B4J Tutorial javafx charts / graphs - LineChart, PieChart, BarChart, AreaChart, Horizontal BarChart, Stacked BarChart, Stacked AreaChart

This is an "inline java code" example for the javafx line chart. It has very basic functionality at present.

You will need javafx.controls.jar. I found the jar on my computer at:
C:\Java\jdk-11.0.1\jdk-11.0.1\javafx\lib

You can download javafx.controls.jar from here:


Find it on your computer and copy it to your B4J additional libs folder.
The attached project will draw the below line chart (provision for 5 x series to be added)
You can add all the other charts in a similar way (bar charts, pie charts, etc, etc - browse the web to see what other chats are available via javafx.
Check the linechartcolors.css file in the /Files folder of the project - it adds the styling used in this example.

Please note: I have no intention to take this project any further (other than for personal use). Change it and add additional features and classes to your liking

Probably not the best way to do the javafx charts. Best will probably be to do a fully fledged wrapper for it. But it is working.....

Enjoy....;)

linechartimage.png


Main code:
B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

#AdditionalJar: javafx.controls

'SEE THE CSS FILE IN THE /FILES FOLDER FOR STYLES THAT ARE USED FOR THE LINE CHART

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private xui As XUI

    Dim lc1 As linechart
    Dim myLineChart As JavaObject

End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show

    'the name of the CSS file in use for the line chart is "linechartcolors.css"
    MainForm.Stylesheets.Add(File.GetUri(File.DirAssets, "linechartcolors.css"))
    'Initialize the chart
    lc1.Initialize
    'set the title - see the css file for setting the title color
    lc1.Title = "Some Arbitrary Data"

    'set the x-axis "values"
    lc1.Xvalues = Array As String("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
    lc1.XAxisTitle = "Months of the year"

    'set series 1 y-axis data
    lc1.Yvalues_1 = Array As Float(153.7, 144.3, 198.5, 177.3, 145.8, 201.6, 113.8, 174.2, 112.5, 133.8, 199.7, 113.1)
    lc1.SeriesName_1 = "Series A"

    'set series 2 y-axis data
    lc1.Yvalues_2 = Array As Float(443.7, 434.3, 488.5, 467.3, 435.8, 491.6, 453.8, 464.2, 42.5, 423.8, 489.7, 43.1)
    lc1.SeriesName_2 = "Series B"

    'set series 3 y-axis data
    lc1.Yvalues_3 = Array As Float(-233.7, -224.3, -298.5, -257.3, -225.8, -281.6, -243.8, -254.2, -208.5, -213.8, -279.7, -207.1)
    lc1.SeriesName_3 = "Series C"

    'set series 4 y-axis data
    lc1.Yvalues_4 = Array As Float(33.7, 24.3, 98.5, 57.3, 25.8, 81.6, 43.8, 54.2, 8.5, 13.8, 79.7, 7.1)
    lc1.SeriesName_4 = "Series D"

    'set series 5 y-axis data
    lc1.Yvalues_5 = Array As Float(233.7, 224.3, 298.5, 257.3, 225.8, 281.6, 243.8, 254.2, 208.5, 213.8, 279.7, 207.1)
    lc1.SeriesName_5 = "Series E"

    'draw the chart and then get it as a java object
    myLineChart = lc1.drawLineChart
    'add the line chart object to the root pane
    MainForm.RootPane.AddNode(myLineChart,0,0,600,500)

End Sub

Code in class "linechart"
B4X:
Sub Class_Globals
    Private fx As JFX
    Dim nativeMe, lc As JavaObject
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize

    nativeMe = Me

End Sub

public Sub drawLineChart() As JavaObject

    lc = nativeMe.RunMethod("DrawChart", Null)
    Return lc

End Sub

public Sub setXvalues (xvals() As String)

    nativeMe.RunMethod("setXvals", Array(xvals))

End Sub

public Sub setYvalues_1 (yvals_1() As Float)

    nativeMe.RunMethod("setYvals_1", Array(yvals_1))

End Sub

public Sub setYvalues_2 (yvals_2() As Float)

    nativeMe.RunMethod("setYvals_2", Array(yvals_2))

End Sub

public Sub setYvalues_3 (yvals_3() As Float)

    nativeMe.RunMethod("setYvals_3", Array(yvals_3))

End Sub

public Sub setYvalues_4 (yvals_4() As Float)

    nativeMe.RunMethod("setYvals_4", Array(yvals_4))

End Sub

public Sub setYvalues_5 (yvals_5() As Float)

    nativeMe.RunMethod("setYvals_5", Array(yvals_5))

End Sub

public Sub setTitle(title As String)

    nativeMe.RunMethod("setTitle", Array(title))

End Sub

public Sub setXAxisTitle(XAxisTitle As String)

    nativeMe.RunMethod("setXaxisTitle", Array(XAxisTitle))

End Sub

public Sub setSeriesName_1 (sname As String)

    nativeMe.RunMethod("setSeriesName_1", Array(sname))

End Sub

public Sub setSeriesName_2 (sname As String)

    nativeMe.RunMethod("setSeriesName_2", Array(sname))

End Sub

public Sub setSeriesName_3 (sname As String)

    nativeMe.RunMethod("setSeriesName_3", Array(sname))

End Sub

public Sub setSeriesName_4 (sname As String)

    nativeMe.RunMethod("setSeriesName_4", Array(sname))

End Sub

public Sub setSeriesName_5 (sname As String)

    nativeMe.RunMethod("setSeriesName_5", Array(sname))

End Sub

#if Java

    import javafx.application.Application;
    import javafx.stage.Stage;
    import javafx.geometry.Insets;
    import javafx.geometry.Side;
    import java.awt.Color;
    import javafx.collections.*;
    import javafx.event.EventHandler;
    import javafx.scene.*;
    import javafx.scene.chart.*;
    import javafx.scene.chart.XYChart.Data;

    private static XYChart.Series series_1, series_2, series_3, series_4, series_5;

    public static LineChart DrawChart() {
            final CategoryAxis xAxis = new CategoryAxis();
     //     final NumberAxis xAxis = new NumberAxis();
            final NumberAxis yAxis = new NumberAxis();
            xAxis.setLabel(xAxisTitle);
            xAxis.setSide(Side.TOP);
            //creating the chart
            final LineChart lineChart =
                    new LineChart(xAxis,yAxis);
              
            lineChart.setTitle(title);
      
            //defining a series

            //populating the series with data
            if (xvals.length > 0) {

                if (yvals_1 != null) { 
                    series_1 = new XYChart.Series();
                    series_1.setName(seriesname_1);
                    for (int i = 0; i < xvals.length; i++) {
                        series_1.getData().add(new XYChart.Data(xvals[i], yvals_1[i]));
                    }
                    lineChart.getData().add(series_1);
                    series_1.getNode().setOnMouseClicked(e -> BA.Log("Clicked on 1st series"));         
                }
          
                if (yvals_2 != null) {
                    series_2 = new XYChart.Series();
                    series_2.setName(seriesname_2);         
                    for (int i = 0; i < xvals.length; i++) {
                        series_2.getData().add(new XYChart.Data(xvals[i], yvals_2[i]));
                    }
                    lineChart.getData().add(series_2);
                    series_2.getNode().setOnMouseClicked(e -> BA.Log("Clicked on 2nd series"));         
                }     
          
                if (yvals_3 != null) {
                    series_3 = new XYChart.Series();
                    series_3.setName(seriesname_3);         
                    for (int i = 0; i < xvals.length; i++) {
                        series_3.getData().add(new XYChart.Data(xvals[i], yvals_3[i]));
                    }
                    lineChart.getData().add(series_3);
                    series_3.getNode().setOnMouseClicked(e -> BA.Log("Clicked on 3rd series"));         
                } 
          
                if (yvals_4 != null) {
                    series_4 = new XYChart.Series();
                    series_4.setName(seriesname_4);         
                    for (int i = 0; i < xvals.length; i++) {
                        series_4.getData().add(new XYChart.Data(xvals[i], yvals_4[i]));
                    }
                    lineChart.getData().add(series_4);
                    series_4.getNode().setOnMouseClicked(e -> BA.Log("Clicked on 4th series"));         
                }             
          
                if (yvals_5 != null) {
                    series_5 = new XYChart.Series();
                    series_5.setName(seriesname_5);         
                    for (int i = 0; i < xvals.length; i++) {
                        series_5.getData().add(new XYChart.Data(xvals[i], yvals_5[i]));
                    }
                    lineChart.getData().add(series_5);
                    series_5.getNode().setOnMouseClicked(e -> BA.Log("Clicked on 5th series"));         
                }                     
            }
      
           lineChart.setAnimated(true);
           lineChart.setCursor(Cursor.CROSSHAIR);
           lineChart.setCreateSymbols(true);          //draw the little circles at each of the data points

           return lineChart;
    }

    private static String[] xvals;
    public void setXvals(String[] xvals) {
        this.xvals = xvals;
    }

    private static String title = "";
    public void setTitle(String title) {
        this.title = title;
    }

    private static String seriesname_1 = "";
    private static String seriesname_2 = "";
    private static String seriesname_3 = "";
    private static String seriesname_4 = "";
    private static String seriesname_5 = "";

    public void setSeriesName_1 (String seriesname_1) {
        this.seriesname_1 = seriesname_1;
    }

    public void setSeriesName_2 (String seriesname_2) {
        this.seriesname_2 = seriesname_2;
    }

    public void setSeriesName_3 (String seriesname_3) {
        this.seriesname_3 = seriesname_3;
    }

    public void setSeriesName_4 (String seriesname_4) {
        this.seriesname_4 = seriesname_4;
    }

    public void setSeriesName_5 (String seriesname_5) {
        this.seriesname_5 = seriesname_5;
    }

    private static float[] yvals_1, yvals_2, yvals_3, yvals_4, yvals_5;

    public void setYvals_1(float[] yvals_1) {
        this.yvals_1 = yvals_1;
    }

    public void setYvals_2(float[] yvals_2) {
        this.yvals_2 = yvals_2;
    }

    public void setYvals_3(float[] yvals_3) {
        this.yvals_3 = yvals_3;
    }

    public void setYvals_4(float[] yvals_4) {
        this.yvals_4 = yvals_4;
    }

    public void setYvals_5(float[] yvals_5) {
        this.yvals_5 = yvals_5;
    }

    private static String xAxisTitle = "";
    public void setXaxisTitle(String xAxisTitle) {
        this.xAxisTitle = xAxisTitle;
    }

#End If
 

Attachments

  • LineChart.zip
    4.4 KB · Views: 381
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
Have added some events to LineChart, VerticalBarChart, HorizontalBarChart, PieChart, and StackedBarChart. Click on a series - the labels will display the "value" clicked on (xValue, yValue, seriesName). Have "circled" the reported "clicked-on" values in the below image (values reported in labels that have been added to each of the charts). See the code in "Main" where the labels are added.



JavafxCharts.png


The "events" raised in "Main" - called from the respective chart classes:
B4X:
Sub PieChartValueClicked (mlst As Object)
    Dim mylist As List = mlst
    pclabel.Text = ""
    For i = 0 To mylist.Size - 1
        pclabel.Text = pclabel.Text & mylist.Get(i) & " "
    Next
   
End Sub

Sub linechart_value_clicked (mylist As List)
   
    lclabel.Text = ""
    For i = 0 To mylist.Size-1
        lclabel.Text = lclabel.Text & mylist.get(i) & " "
    Next
   
End Sub

Sub StackedBarChartValueClicked (val As Object)
   
    sbclabel.Text = ""
    Dim mylist As List = val
    For i = 0 To mylist.Size-1
        sbclabel.Text = sbclabel.Text & mylist.get(i) & " "
    Next
   
End Sub

Sub VerticalBarChartValueClicked (val As Object)
   
    vbclabel.Text = ""
    Dim mylist As List = val
    For i = 0 To mylist.Size-1
        vbclabel.Text = vbclabel.Text & mylist.get(i) & " "
    Next
   
End Sub

Sub HorizontalBarChartValueClicked (val As Object)
   
    hbclabel.Text = ""
    Dim mylist As List = val
    For i = 0 To mylist.Size-1
        hbclabel.Text = hbclabel.Text & mylist.get(i) & " "
        Log(mylist.get(i))
    Next
   
End Sub
 

Attachments

  • JavaFXCharts.zip
    16.4 KB · Views: 261
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
Here is an update for the Pie Chart:
1. Make sure you have javafx.controls.jar in your B4J additional library folder. See the link in post #1 (above) where you can download it from.
2. Click on button "Toggle" to change the appearance of the Pie Chart
3. Click on a pie slice to view the values (value and label) of the slice that you clicked on
4. Use the handles of the Form and resize the form - the Pie Chart should follow suite.

Have added as many comments as possible to the code

1619963757872.png


B4J Main module code:
B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

#AdditionalJar: javafx.controls

Sub Process_Globals
    Private MainForm As Form
    Private xui As XUI
    Private Root As B4XView 'ignore
    Private Pane1 As Pane
    Dim pc1 As piechart                                             'a reference to class "piechart"
    Dim myPieChart As JavaObject                                    'the class "piechart" will return an Object and we will then add it to the Pane
    Private Button1 As Button                                       'it will close MainForm when clicked
    Private Button2 As Button                                       'used for changing some features of the Pie Chart
    Private fx As JFX
    Private pclabel As Label                                        'this label will be used to show the values of the slices clicked on the Pie Chart
    Dim toggle As Int = 0                                           'tracking the state of Button2 "clicked"
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show

    pc1.Initialize                                                                                  'initialize an instance of call "piechart"
    pc1.Title = "Fruit Exports"                                                                     'set the Pie Chart title
    pclabel.Text = ""                                                                               'set the label text to "nothing" -> the label that displays the values of slices clicked
'    MainForm.Stylesheets.Add(File.GetUri(File.DirAssets, "chartcolors.css"))    'uncomment to use the styling in "chartcolors.css" - see the /Files folder

    pc1.PieLabels = Array As String("Apples", "Pears", "Bananas", "Grapes", "Oranges", "Lemon", "Avocado", "Berries")  'add the Pie Chart Labels for each Pie Chart slice
    pc1.PieValues = Array As Float(25.0, 30.0, 10.0, 15.0, 10.0, 5.0, 4.0, 1.0)                                        'add the data for each Pie Chart slice
    pc1.StartAngle = 180                                                                                               'set the start angle to "xxx" degrees -> slice 1
    pc1.ShowCrossHair = True                                                                                           'show/dont show the cross hair
    pc1.LabelsVisible = True                                                                                           'show/dont show the pie chart labels
    pc1.LegendVisible = True                                                                                           'show/dont show the Legend
    pc1.LabelLineLength = 15.0                                                                                         'the line length from the slice to the slice label
    pc1.Clockwise = False                                                                                              'draw the Pie chart clockwise / anti-clockwise
    pc1.LegendSide = pc1.Legend_Side_Right                                                                             'position the Legend of the Pie Chart
    myPieChart = pc1.drawPieChart                                                                                      'draw the pie chart and return an instance as a java object
    Pane1.AddNode(myPieChart,Pane1.Width*0.15,Pane1.Height*0.15,Pane1.Width*0.7,Pane1.Height*0.7)                      'add the Pie Chart (java object) to the pane at the specified position
      
End Sub

Private Sub Button1_Click

    MainForm.Close
  
End Sub

Sub PieChartValueClicked (mlst As Object)                    'This is an Event and is raised from class "piechart" - the data comes in as a List (passed to here as an object)
    pclabel.Text = ""
    Dim mylist As List = mlst                                'define List and assign the returned object to the list
    pclabel.Text = ""
    For i = 0 To mylist.Size - 1                             'cycle through the list to get individual returned values
        pclabel.Text = pclabel.Text & mylist.Get(i) & " "    'display the "clicked" values in the label
    Next
  
End Sub
                                                  
Sub MainForm_Resize (Width As Double, Height As Double)      'TAKE NOTE - THE PIE CHART OBJECT is the 2nd NODE of the Pane in this example
    Pane1.GetNode(2).Left = Width*0.15                       'change the Left position of the pie chart when the form/page is resized
    Pane1.GetNode(2).Top = Height*0.15                       'change the Top position of the pie chart when the form/page is resized
    Pane1.GetNode(2).PrefWidth = Width * 0.7                 'change the Width of the pie chart when the form/page is resized
    Pane1.GetNode(2).PrefHeight = Height * 0.7               'change the Height of the pie chart when the form/page is resized
End Sub

Private Sub Button2_Click
  
    Dim mrnd As Int = Rnd(0,4)                                'select a random number from 0 to 3 that will determine the Legend position (LEFT, RIGHT, TOP, BOTTOM)
    Dim myangle As Int = Rnd(0,360)                           'select a random start angle for the pie chart (1st series)
  
    If mrnd = 0 Then pc1.LegendSide = pc1.Legend_Side_Left    'add the Legend to the LEFT of the pie chart
    If mrnd = 1 Then pc1.LegendSide = pc1.Legend_Side_Right   'add the Legend to the RIGHT of the pie chart
    If mrnd = 2 Then pc1.LegendSide = pc1.Legend_Side_Top     'add the Legend to the TOP of the pie chart
    If mrnd = 3 Then pc1.LegendSide = pc1.Legend_Side_Bottom  'add the Legend to the BOTTOM of the pie chart

    If toggle = 0 Then
        pc1.LabelLineLength = 15.0                            'the length of the label line from the slice to the label
        pc1.LabelsVisible = True                              'setting the visibility of the slice labels
        pc1.LegendVisible = False                             'setting the visibility of the Legend
        pc1.Clockwise = True                                  'draw the pie chart clockwise or anti-clockwise
        pc1.StartAngle = myangle                              'apply the randomly selected starting angle of the pie chart
        toggle = 1                                            'toggle when Button2 is clicked
    Else
        pc1.LabelLineLength = 8.0                             '.....the same as above but for toggle state  = 1
        pc1.LabelsVisible = True
        pc1.LegendVisible = True
        pc1.Clockwise = False
        pc1.StartAngle = myangle
        toggle = 0                                            'toggle the state when Button2 is clicked
      
    End If
  
End Sub

Code in class "piechart":
B4X:
Sub Class_Globals
    Private fx As JFX
    Dim nativeMe, pc As JavaObject                                'pc holds the Pie Chart object
    Public Legend_Side_Left As String = "Left"                    'set the Legend position to the LEFT of the Pie Chart
    Public Legend_Side_Right As String = "Right"                  'set the Legend position to the RIGHT of the Pie Chart
    Public Legend_Side_Top As String = "Top"                      'set the Legend position to the TOP of the Pie Chart
    Public Legend_Side_Bottom As String = "Bottom"                'set the Legend position to the BOTTOM of the Pie Chart
  
End Sub

'Initializes the piechart object
Public Sub Initialize
  
    nativeMe = Me                                                 'initialize an instance of the Pie Chart object

End Sub

'Draw the pie chart
public Sub drawPieChart() As JavaObject
  
    pc = nativeMe.RunMethod("DrawChart", Null)
    Return pc
  
End Sub

'Set the labels of the pie chart slices
public Sub setPieLabels (xvals() As String)
  
    nativeMe.RunMethod("setPieLabels", Array(xvals))
  
End Sub

'Set the values of the pie chart slices
'Convert the values to % prior to passing it to this sub - if you want to show each slice as a percentage of the total value
public Sub setPieValues (yvals() As Float)
  
    nativeMe.RunMethod("setPieValues", Array(yvals))
  
End Sub

'Set the title of the pie chart
public Sub setTitle(title As String)
  
    nativeMe.RunMethod("setTitle", Array(title))
  
End Sub

'Show the crosshair (True or False)
Public Sub setShowCrossHair (show As Boolean)
  
    nativeMe.RunMethod("setShowCrossHair", Array(show))
  
End Sub

'Set the starting angle of the pie chart
public Sub setStartAngle (startangle As Int)
  
    nativeMe.RunMethod("setStartAngle", Array(startangle))
  
End Sub

'Set the visibility of the labels of the pie chart slices
Public Sub setLabelsVisible(labelsVisible As Boolean)
  
    nativeMe.RunMethod("setLabelsVisible", Array(labelsVisible))
  
End Sub

'Set the visibility of the legend
Public Sub setLegendVisible(legendVisible As Boolean)
  
    nativeMe.RunMethod("setLegendVisible", Array(legendVisible))
  
End Sub

'Set the visibility of the legend
Public Sub setLabelLineLength(labelLineLength As Float)
  
    nativeMe.RunMethod("setLabelLineLength", Array(labelLineLength))
  
End Sub

'draw the pie chart clockwise / anti-clockwise
Public Sub setClockwise(clockwise As Boolean)
  
    nativeMe.RunMethod("setClockwise", Array(clockwise))
  
End Sub

'Set the position of the Legend (it can be LEFT, RIGHT, TOP, BOTTOM)
public Sub setLegendSide(whatside As String)
  
    nativeMe.RunMethod("setLegendSide", Array(whatside))
  
End Sub

'callback is called from the inline Java code - ba.raiseEventFromUI(this, "callback", mylist);
Private Sub callback (mylist As Object)
  
    CallSubDelayed2(Main,"PieChartValueClicked", mylist)      'call/raise event in PieChartValueClicked of module Main
                                                              'see the "ba.raiseEventFromUI(this, "callback", mylist);" in the inline java code
End Sub

'INLINE JAVA CODE BELOW

#if Java

//START OF IMPORTS
import javafx.scene.chart.*;
import javafx.geometry.Side;
import javafx.scene.control.Label;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import java.util.*;
import javafx.scene.*;
import javafx.scene.chart.XYChart.*;
//END OF IMPORTS

//DECLARING VARIABLES
private static BA ba;
PieChart piechart;

    //called to draw the Pie Chart after all attributes have been set
    public PieChart DrawChart() {
              
        piechart = new PieChart();                                                        //new instance of the PieChart object

        for (int i = 0; i < xvals.length; i++) {                                          //add data to the Pie Chart - cycle through the lenght of the array holding the label names
      
            PieChart.Data slice = new PieChart.Data(xvals[i], yvals[i]);                  //create a new slice to be added to the Pie Chart with the applicable xvals and yvals values
            piechart.getData().add(slice);                                                //add the slice to the Pie Chart.
      
        }
      
        piechart.setTitle(title);                                                         //set the title of the Pie Chart
        piechart.setLabelLineLength(labelLineLength);                                     //set the label line length that extends from the slice to the text lable of the slice
        if (whatside.equals("Left"))                                                      //set the position of the Legend (LEFT, TOP, RIGHT, BOTTOM)
            piechart.setLegendSide(Side.LEFT);
        if (whatside.equals("Right"))
            piechart.setLegendSide(Side.RIGHT);     
        if (whatside.equals("Top"))
            piechart.setLegendSide(Side.TOP); 
        if (whatside.equals("Bottom"))
            piechart.setLegendSide(Side.BOTTOM);                     
        piechart.setClockwise(clockwise);                                                //draw the Pie Chart clockwise or anti-clockwise
        piechart.setLabelsVisible(labelsVisible);                                        //set the visibility of the labels of the Pie Chart slices
        piechart.setLegendVisible(legendVisible);                                        //set the visibility of the Pie Chart Legend
        piechart.setStartAngle(startangle);                                              //set the starting angle of the Pie Chart - reference is the first slice
        if (showcrosshair == true)                                                       //show or don't show the crosshair when the mouse is hovering over the Pie Chart
            piechart.setCursor(Cursor.CROSSHAIR);
      
        for (final PieChart.Data data : piechart.getData()) {                            //add a MOUSE_PRESSED event to the Pie Chart
            data.getNode().addEventHandler(MouseEvent.MOUSE_PRESSED,                     //it will get/return the name and value of the slice clicked on via the "callback" event
                new EventHandler<MouseEvent>() {
                    @Override public void handle(MouseEvent e) {
                        List<Object> mylist = new ArrayList<>();                                  //create an ArrayList that will be used to return data to "callback"
                        mylist.add(data.getName());                                               //add the name of the pie slice clicked on
                        mylist.add(String.valueOf(data.getPieValue()) + "%");                     //add the value of the pie slice clicked on
                        ba.raiseEventFromUI(this, "callback", mylist);                              //pass the ArrayList to the "callback" method in the B4A code via an Event - it will be received as an Object
                        //ba.raiseEventFromUI(this, EventName.toLowerCase(BA.cul) + "_fire", 10);
                     }
                });
        }
        return piechart;                                                                 //return a Pie Chart object - we need it to add the Pie Chart to the Pane in the layout
    }                                                                                    //it is received as a JavaObject in Main

    //add the Pie Chart labels
    private static String[] xvals;
    public void setPieLabels(String[] xvals) {
        this.xvals = xvals;
    }
  
    //add the Pie Chart title
    private static String title = "";
    public void setTitle(String title) {
        this.title = title;
    }

    //add the values of the Pie Chart slices
    private static float[] yvals;
    public void setPieValues(float[] yvals) {
        this.yvals = yvals;
    }
  
    //show or don't show the crosshair
    private static boolean showcrosshair = false;
    public void setShowCrossHair(boolean showcrosshair) {
        this.showcrosshair = showcrosshair;
    }     
  
    //set the starting angle of the first Pie Chart slice
    private static int startangle = 90;
    public void setStartAngle(int startangle) {
        this.startangle = startangle;     
        if (piechart != null)                                         //if the piechart object != null then we can change the start angle of the fly
            piechart.setStartAngle(startangle);
    }
  
    //show or don't show the labels of the Pie Chart slices
    private static boolean labelsVisible = true;
    public void setLabelsVisible(boolean labelsVisible) {
        this.labelsVisible = labelsVisible;
        if (piechart != null)                                        //if the piechart object != null then we can change the label visibility of the fly
            piechart.setLabelsVisible(labelsVisible);
    }
  
    //show or don't show the Pie Chart Legend
    private static boolean legendVisible = true;
    public void setLegendVisible(boolean legendVisible) {
        this.legendVisible = legendVisible;
        if (piechart != null)                                         //if the piechart object != null then we can change the visibility of the Legend of the fly
            piechart.setLegendVisible(legendVisible);
    } 
  
    //set the line length extending from the slices to their lables
    private static float labelLineLength = 15.0f;
    public void setLabelLineLength(float labelLineLength) {
        this.labelLineLength = labelLineLength;
        if (piechart != null)                                          //if the piechart object != null then we can change the label length of the fly
            piechart.setLabelLineLength(labelLineLength);     
    }     
  
    //draw the Pie Chart clockwise or anti-clockwse
    private static boolean clockwise = true;
    public void setClockwise(boolean clockwise) {
        this.clockwise = clockwise;
        if (piechart != null)                                          //if the piechart object != null then we can change the clockwise/anti-clockwise direction of the fly                   
            piechart.setClockwise(clockwise);
    }
  
    //what side to put the Pie Chart Legend (LEFT, RIGHT, TOP, BOTTOM)
    private static String whatside = "Left";
    public void setLegendSide(String whatside) {
        this.whatside = whatside;     
      
        if ((piechart != null) & (whatside.equals("Left")))            //if the piechart object != null then we can change the position of the fly
            piechart.setLegendSide(Side.LEFT);                         //set the Legend to the LEFT of the Pie Chart
        if ((piechart != null) & (whatside.equals("Right")))
            piechart.setLegendSide(Side.RIGHT);                           //set the Legend to the RIGHT of the Pie Chart     
        if ((piechart != null) & (whatside.equals("Top")))
            piechart.setLegendSide(Side.TOP);                           //set the Legend to the TOP of the Pie Chart
        if ((piechart != null) & (whatside.equals("Bottom")))
            piechart.setLegendSide(Side.BOTTOM);                       //set the Legend to the BOTTOM of the Pie Chart         
    } 
  
#End If


Next exercise - change the values on the fly...
 

Attachments

  • jfxPieChart.zip
    7.6 KB · Views: 224
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
A live Pie Chart (i.e ability to change values on the fly)

1.png


1. Click on a pie slice - the value of the slice clicked on will be displayed in the applicable pie slice. See the code in module Main
B4X:
Sub PieChart_Value_Clicked (mlst As Object)                  'This is an Event and is raised from class "piechart" - the data comes in as a List (passed to here as an object)

    pclabel.Text = ""
    Dim mylist As List = mlst                                'define List and assign the returned object to the list
    'mylist(0) will hold the pie slice name
    'mylist(1) will hold the pic slice value
    'mylist(2) will hold the X position of the slice clicked on
    'mylist(3) will hold the Y position of the slice clicked on
    pclabel.Text = ""

    pclabel.Text = mylist.Get(1)                              'get the slice value
    pclabel.Left = mylist.Get(2) - pclabel.Width/2            'get the X position of the slice clicked on and position the label position correctly
    pclabel.Top = mylist.Get(3) - pclabel.Height/2            'get the Y position of the slice clicked on and position the label position correctly
    pclabel.TextColor = fx.Colors.White                       'set the color of the label displaying the "value" of the pie slice to white
    pclabel.TextSize = 15.0                                      'set the text size of the label displaying the "value" of the pie slice a text size value
    
End Sub
2. Click on button "Toggle" - it will amongst others add / remove a slice (named "Other Fruits")

See the link in post #1 for the required jar that you need in your B4J additional library folder.
Edit the "CSS" file in the /Files folder of the B4J project to apply different colors to the Pie Chart slices

Uncomment this line in the Main module to apply the styles in the "CSS" file:
B4X:
'    MainForm.Stylesheets.Add(File.GetUri(File.DirAssets, "chartcolors.css"))    'uncomment to use the styling in "chartcolors.css" - see the /Files folder

If you want the slices to be displayed as a percentage of all slice values then you need to calculate the % values (x100) in your B4J code.
 

Attachments

  • jfxPieChart.zip
    8.1 KB · Views: 222

Johan Schoeman

Expert
Licensed User
Longtime User
An update for the pie chart (see post#1 for the link to download javafx.controls.jar - you need to have the jar in your B4J additional libs folder):


piec.gif
 

Attachments

  • jfxPieChart.zip
    9.1 KB · Views: 265
Last edited:
Top