B4J Library jCharts

Informatix

Expert
Licensed User
Here's my first library for B4J. It's a wrapper of javafx.scene.chart with additional functions and classes.

jCharts.jpg
chart2.jpg


To take a snapshot of a chart, set its animated property to False before adding the data or wait until all animations are over.

Changelog:
v1.21:
- I added a workaround for a bug in OpenJDK 11 (thanks to Chris2)

v1.2:
- XAxis and YAxis created by the designer can now raise events with the default event prefix "XAxis" / "YAxis";
- I added the LegendChanged event to all charts;
- I fixed a bug (NullPointerException) in GetChildStyleMap and StyleMap.

v1.11:
- I added the SetChildStyleMap2 function;
- I modified the fourth demo to show a simple way to add the colored bands.

v1.1:
- I added the Plot event to all charts except PieChart;
- I added a demo to show how to use the Plot event (this project requires jGraphicLib);
- I modified the third demo to use a layout made with the designer.

v1.0:
- All charts can be added as custom views in the visual designer;
- I added the Width and Height properties to all charts and axis;
- I added the Series property to XYCoord;
- I added the MouseToData function to all charts and removed the EventPrefixForPlot parameter from Initialize (MouseToData is more convenient than events);
- I modified the second demo to show MouseToData in use;
- I modified the third demo so that the slider value sets the upper bound of the displayed series.

v0.9:
- I added ForceZeroInRange and TickUnit to NumberAxis;
- I added RemoveAllData to PieChart;
- I added FindNearestX to XYSeries;
- I added FindSeries and RemoveAllSeries to all charts using series;
- I added Padding to all charts;
- I added a new example and some documentation.
 

Attachments

Last edited:

Harris

Expert
Licensed User
Sweet....

Can you make this work with ABMaterial? ()wrapper, plugin, etc)..

I am using the Chartist lib with ABM but it is not giving the results I need.
Particularly, the X axis labels don't (can't) show the date/times that need to be displayed so one has a reference to the x grid. And if it did, it is not rotated to 90 degrees where it wont overlap the next label.

My data shows second by second the activity for a period (hour, 4 hours, 12 hours or 24 hours). Granted, this is a huge amount of data to stuff in a line graph (each hour is (60*60 data points)).

The y axis is fine (speed in MPH), the x axis doesn't show the (date/time - rotated 90 degrees - left or right) to tell the time of day this data point occurred. They are simply (i incs) for each data point accumulated - with no reference to date/time.

Thanks



chart1.jpg
 

Informatix

Expert
Licensed User
Sweet....

Can you make this work with ABMaterial? ()wrapper, plugin, etc)..

I am using the Chartist lib with ABM but it is not giving the results I need.
Particularly, the X axis labels don't (can't) show the date/times that need to be displayed so one has a reference to the x grid. And if it did, it is not rotated to 90 degrees where it wont overlap the next label.

My data shows second by second the activity for a period (hour, 4 hours, 12 hours or 24 hours). Granted, this is a huge amount of data to stuff in a line graph (each hour is (60*60 data points)).

The y axis is fine (speed in MPH), the x axis doesn't show the (date/time - rotated 90 degrees - left or right) to tell the time of day this data point occurred. They are simply (i incs) for each data point accumulated - with no reference to date/time.

Thanks



View attachment 49262
I don't know ABMaterial yet and I create only libraries that I need so...
Moreover Chartist is a Javascript lib, so if ABMaterial expects something in Javascript, what you ask will never happen.
 

Informatix

Expert
Licensed User
Yes, this is the case. However, if your lib can output to an image, it could be useful for static charts in ABMaterial (using an ABMImage).
Unfortunately, the Snapshot feature does not grab the whole chart (axis and plotted data are missing). I didn't look yet at what that function does exactly so it's maybe possible to improve it.
 

Informatix

Expert
Licensed User
Unfortunately, the Snapshot feature does not grab the whole chart (axis and plotted data are missing). I didn't look yet at what that function does exactly so it's maybe possible to improve it.
Problem solved. Fixed for the next version.
 

Informatix

Expert
Licensed User
Problem solved. Fixed for the next version.
Finally, I removed my solution for snapshots in the new version because it didn't work in a particular case. So my solution for snapshots is just an advice:
To take a snapshot of a chart, set its animated property to False before adding the data or wait until all animations are over.
 

Harris

Expert
Licensed User
I like your example 3 - and all of jChart.

Is it possible to zoom in on the entire data - to show a selected section within the subset?

Your example shows the slider growing from small to all. When all, I would like to "rubber band" a section (to zoom in) and show it within screen width.
This would, for example, show when Y (speed in MPH) was greater than company limits (for how long and how high).

Hope you get my meaning.

Thanks
 

Informatix

Expert
Licensed User
I like your example 3 - and all of jChart.

Is it possible to zoom in on the entire data - to show a selected section within the subset?

Your example shows the slider growing from small to all. When all, I would like to "rubber band" a section (to zoom in) and show it within screen width.
This would, for example, show when Y (speed in MPH) was greater than company limits (for how long and how high).

Hope you get my meaning.

Thanks
I modified a little bit my example Chart3 so the slider now sets the zoom factor. Use the MouseDragged event to select the data to zoom in on and create the series to draw from the full series like I do in sldLimitX_ValueChange, but with two boundaries (If XY.X >= value_drag_begin and XY.X <= value_drag_end Then).
 

Attachments

Harris

Expert
Licensed User
Going good so far...

Following your new EX 3 sample. Learning plenty... Got Zooming in and out of FullSeries cased (however a learning curve for sure - using pressed and released since no drag events would expose down / up??).

When form is first presented, it is sized per primary screen. When I drag to second screen, which is much larger, I click the button "Fit Graph to Screen" - which expands the graph to width and height of new screen - nice...

Been struggling with this: How to convert X (Time values - long) to DateTime.Date & Time to show as labels (as string) rotated to 90 degrees.
There must be a way... Need code? Can supply...

EDIT:

Actually, there are two ways to accomplish this question above. Use Dim XAxisL As CategoryAxis or

B4X:
    'LINE CHART
    Dim XAxisL As NumberAxis
    XAxisL.Initialize("XAxisL")
    XAxisL.Label = "Time"
    XAxisL.AutoRanging = True
    XAxisL.ForceZeroInRange = False
    XAxisL.TickLabelRotation = 90
    XAxisL.TickMarkVisible = False
    XAxisL.TickLength = 5


' This converts the number to a time string!
Sub XAxisL_ToString(Number As Object) As String
    Dim LngNbr As Long = Number
    Return DateTime.Time(LngNbr)
End Sub
With some CSS, and much more learning, I can make this presentable - rather than basic desktop drab... (examined some posts already)
Like a friend use to say, "Make it work, you can always make it pretty later"...

Thanks
 

Attachments

Last edited:

Harris

Expert
Licensed User
Now closer with styling...
The following code styles the X axis... How to style the Y?

I have referred to:
https://docs.oracle.com/javafx/2/charts/css-styles.htm

for styling advice, but they only go so far...

Is there a doc which shows all the styling that can be performed?

Each of the 11 (pages), for the day selected in the table, will plot an hours worth of data (for each second of the hour).
I tried to load the entire day (35000 points in many cases), but it took over 10 minutes to load.
This works well - loading a smaller subset. One can zoom in on any plot, down to the second. Sweet!!!

Thanks


B4X:
    Dim FirstLineStyle As Map = LineChart.GetChildStyleMap(".default-color0.chart-series-line")
    FirstLineStyle.Put("-fx-stroke", "black")
    FirstLineStyle.Put("-fx-stroke-width", "1px")
    LineChart.SetChildStyleMap(".default-color0.chart-series-line", FirstLineStyle)

    Dim FirstLineStyle As Map = LineChart.GetChildStyleMap(".axis")
    FirstLineStyle.Put("-fx-font-size", "20px" )
    FirstLineStyle.Put("-fx-tick-length", "15" )
    FirstLineStyle.Put("-fx-tick-label-fill", "blue" )
    FirstLineStyle.Put("-fx-tick-label-font-size", "1.2em" )
    FirstLineStyle.Put("-fx-font-family", "Tahoma" )
    FirstLineStyle.Put("-fx-minor-tick-length", "10" )
    LineChart.SetChildStyleMap(".axis", FirstLineStyle)


    Dim FirstLineStyle As Map = LineChart.GetChildStyleMap(".axis-tick-mark")
    FirstLineStyle.Put("-fx-stroke","black")
    FirstLineStyle.Put("-fx-stroke-width","2")
    LineChart.SetChildStyleMap(".axis-tick-mark", FirstLineStyle)


    Dim FirstLineStyle As Map = LineChart.GetChildStyleMap(".axis-minor-tick-mark")
    FirstLineStyle.Put("-fx-stroke","black")
    FirstLineStyle.Put("-fx-stroke-width","1")
    LineChart.SetChildStyleMap(".axis-minor-tick-mark", FirstLineStyle)

jchart1.jpg
 
Last edited:

Harris

Expert
Licensed User
Zoom and Zoomed in feature... Drag to zoom (left to right - creates visual canvas rect), let go and magic. How nice!
To un-zoom (restore the original view) - drag from right to left...

Note: I can't image what I would have to learn in order to do this with Google Charts - in JavaScript! I know it can, but it is well beyond my abilities. Need wrapper in ABM for Google charts - so THIS stuff can be accomplished (OR wrap jCharts).

jchart1_zoom.jpg


jchart1_zoomed_in.jpg
 
Last edited:

Informatix

Expert
Licensed User
B4X:
   FirstLineStyle.Put("-fx-tick-length", "15" )
    FirstLineStyle.Put("-fx-tick-label-fill", "blue" )
    FirstLineStyle.Put("-fx-tick-label-font-size", "1.2em" )
    FirstLineStyle.Put("-fx-font-family", "Tahoma" )
    FirstLineStyle.Put("-fx-minor-tick-length", "10" )
Please note that some settings can be done via the class properties (Axis.TickLabelFont, Axis.MinorTickLength, etc.).
All CSS settings can be found here: https://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html#charts
 

Informatix

Expert
Licensed User
Dear Informatix,
Does this library support real-time plotting? If so how can this be done?
Yes, just add your data to the graph when they are available. Set Animated to false for the chart or it will perform an animation for each new data.
 

dk9uv

Member
Licensed User
Hi Harris,

I am struggling with your example to show nicely formatted time labels at the x axis instead of plain numbers. Could you please give me a more detailed explanation?

Thanks very much

Chris
 

Harris

Expert
Licensed User
Hi Harris,

I am struggling with your example to show nicely formatted time labels at the x axis instead of plain numbers. Could you please give me a more detailed explanation?

Thanks very much

Chris
It is shown in post 10 above.

Dim XAxisL As NumberAxis '(uses number values)


- add this to your code....
' This converts the number to a time string!
' XAxisL.Initialize("XAxisL") - param defines the event name

Sub XAxisL_ToString(Number As Object) AsString
Dim LngNbr As Long = Number
Return DateTime.Time(LngNbr)
End Sub

Add long values to the X list - the event above will convert it to a time string (XAxisL_ToString)
Dim dt As Long
dt = mp.Get("1") ' 1 = datetime for X axis
rngdate.Add(dt) ' add it to list


The axis font size, color and tick marks are in post 11.

There is an example of formatting numbers in the Chart2 example. That is where I discovered it.
 
Last edited:

dk9uv

Member
Licensed User
It is shown in post 10 above.

Dim XAxisL As NumberAxis '(uses number values)


- add this to your code....
' This converts the number to a time string!
' XAxisL.Initialize("XAxisL") - param defines the event name

Sub XAxisL_ToString(Number As Object) AsString
Dim LngNbr As Long = Number
Return DateTime.Time(LngNbr)
End Sub

Add long values to the X list - the event above will convert it to a time string (XAxisL_ToString)
Dim dt As Long
dt = mp.Get("1") ' 1 = datetime for X axis
rngdate.Add(dt) ' add it to list


The axis font size, color and tick marks are in post 11.

There is an example of formatting numbers in the Chart2 example. That is where I discovered it.

Hi Harris,

great, I forgot the initialization with the event name prefix. No it works prefectly.

Thanks
Chris
 

dk9uv

Member
Licensed User
Another question about formatting axes:

There are 3 possibilities (example):

a.) XAxisL.TickLabelFont=fx.DefaultFont(20) but not all properties available

b.) CSSUtils.SetStyleProperty(XAxisL,"-fx-tick-label-font-size","20px")

c.) Dim FirstLineStyle As Map = LineChartSensorData.GetChildStyleMap(".axis")
FirstLineStyle.Put("-fx-tick-label-font-size", "20px" )
LineChartSensorData.SetChildStyleMap(".axis", FirstLineStyle)

I wonder how to access some styles of the YAxisL (child axis-tick-mark)
e.g. axis-tick-mark fx-stroke-width

(XAxisL works see post #11, but how to access the YAxisL?)
 
Top