B4J Tutorial Raspberry Pi B4J UI Applications with Liberica JDK

Discussion in 'B4J Tutorials' started by rwblinn, May 13, 2018.

  1. rwblinn

    rwblinn Well-Known Member Licensed User

    Tutorial Raspberry Pi B4J UI Applications with Liberica JDK
    v20180513

    Objectives
    To build B4J UI applications, using the Liberica JDK10, running on the Raspberry Pi.
    This tutorial covers setup of the Raspberry Pi, Liberica, development hints and few sample applications.

    The B4J UI applications have been tested with:
    * Raspberry Pi 3B+ with HDMI connected monitor Philips 223V
    * Raspberry Pi 2Bv1.1 with 7" touchscreen display

    Especially the 7" touchscreen solution is interesting for f.e. Information Display, Dashboards, Control GPIO and the likes.

    [​IMG]
    Prototype with 7" touchscreen running the CPU-Temperature-Dashboard sample application.

    [​IMG]
    Screenshot of the prototype with 7" touchscreen running the HomeAutomation-Dashboard sample application.

    Credits
    For the shown sample applications, the jGauges library (@Erel) and the xChart class (@klaus) are used. Many thanks to the authors.

    Liberica Information
    As taken from here, Liberica is a 100% open-source Java 10 implementation for Raspberry Pi.
    It is built from the OpenJDK to which BellSoft contributes. Recommend to read the release notes.
    The source is on GitHub.

    Hardware
    Raspberry Pi 3B+ with HDMI connected monitor Philips 223V
    Raspberry Pi 2 with 7" Touchscreen Display

    Software
    Raspberry Pi Raspbian Stretch (Linux raspberrypi 4.14.30-v7+ #1102 SMP Mon Mar 26 16:45:49 BST 2018 armv7l).
    B4J v6.01
    Liberica JDK 10
    Note: Newer software versions might be available after writing this tutorial.

    Raspberry Pi Setup
    For the testing, installed the latest, at the time of developing, Raspberry Pi NOOBS.
    Configuration Modifications
    Increase the GPU Memory: Menu Preferences > Raspberry Pi Configuration > Tab Performance > Field GPU Memory: 512.

    Disable Monitor Sleep
    Code:
    sudo nano /etc/lightdm/lightdm.conf
    Add the following lines to the [Seat*] section:
    Code:
    # Disable monitor sleep
    xserver-command=X -s 
    0 dpms
    Prior Liberica installation run an Raspberry Pi software upgrade and update:
    sudo apt-get update && sudo apt-get upgrade

    Liberica Installation
    On the Raspberry Pi, open a terminal, login as user pi and execute next steps.
    // Create a folder java to store the downloads.
    Code:
    mkdir /home/pi/java
    // Set the created java folder as default
    Code:
    cd /home/pi/java
    // Download the Liberica JDK10 package from BellSoft
    // Note: This example shows JDK10. In the mean time there might be newer versions, i.e. JDK10.0.1.
    Code:
    wget https://github.com/bell-sw/Liberica/releases/download/10/bellsoft-jdk10-linux-arm32-vfp-hflt.deb
    Logging information snippet ...
    --
    2018-04-18 09:33:42--  https://github.com/bell-sw/Liberica/releases/download/10/bellsoft-jdk10-linux-arm32-vfp-hflt.deb
    Saving 
    to: ‘bellsoft-jdk10-linux-arm32-vfp-hflt.deb’
    bellsoft-jdk10-linu 
    100%[===================>] 209.58M   752KB/s    in 4m 48s
    2018-04-18 09:38:31 (745 KB/s) - ‘bellsoft-jdk10-linux-arm32-vfp-hflt.deb’ saved [219758630/219758630]
    // Install the Liberica JDK10 package
    Code:
    sudo apt install ./bellsoft-jdk10-linux-arm32-vfp-hflt.deb
    // Check the installed java and javac versions
    Code:
    java -version
    resulting 
    in: java version "1.8.0_162"
    javac -version
    resulting 
    in: javac 1.8.0_162
    // Set the right javac version (compiler)
    // The list of javac options depends on the installed java versions.
    // Note: Prior using the Liberica JDK (BellSoft) tested also the jdk8.0_161/162.
    Code:
    $sudo update-alternatives --config javac
    There are 4 choices for the alternative javac (providing /usr/bin/javac).
    Code:
    Selection    Path                                                   Priority   Status
    ------------------------------------------------------------
      
    0            /usr/lib/jvm/jdk-10-bellsoft-arm32-vfp-hflt/bin/javac   1902      auto mode
      
    1            /opt/jdk1.8.0_161/bin/javac                             1         manual mode
    2            /opt/jdk1.8.0_162/bin/javac                             1         manual mode
      
    3            /usr/lib/jvm/jdk-10-bellsoft-arm32-vfp-hflt/bin/javac   1902      manual mode
      
    4            /usr/lib/jvm/jdk-7-oracle-arm-vfp-hflt/bin/javac        317       manual mode
    Press <enter> 
    to keep the current choice[*], or type selection number: 3
    update-alternatives: using /usr/lib/jvm/jdk-
    10-bellsoft-arm32-vfp-hflt/bin/javac to provide /usr/bin/javac (javac) in manual mode
    // Set the right java version (runtime)
    // The list of options depends on the installed java versions.
    Code:
    $sudo update-alternatives --config java
    There are 4 choices for the alternative java (providing /usr/bin/java).
    Code:
    Selection    Path                                                  Priority   Status
    ------------------------------------------------------------
      
    0            /usr/lib/jvm/jdk-10-bellsoft-arm32-vfp-hflt/bin/java   1902      auto mode
      
    1            /opt/jdk1.8.0_161/bin/java                             1         manual mode
    2            /opt/jdk1.8.0_162/bin/java                             1         manual mode
      
    3            /usr/lib/jvm/jdk-10-bellsoft-arm32-vfp-hflt/bin/java   1902      manual mode
      
    4            /usr/lib/jvm/jdk-7-oracle-arm-vfp-hflt/jre/bin/java    317       manual mode
    Press <enter> 
    to keep the current choice[*], or type selection number: 3
    update-alternatives: using /usr/lib/jvm/jdk-
    10-bellsoft-arm32-vfp-hflt/bin/java to provide /usr/bin/java (java) in manual mode
    // Check the java and javac versions again = should be the BellSoft java 10 versions
    Code:
    $javac -version
    javac 
    10-BellSoft
    Code:
    $java -version
    openjdk version 
    "10-BellSoft" 2018-03-20
    OpenJDK Runtime Environment (build 
    10-BellSoft+0)
    OpenJDK 
    Server VM (build 10-BellSoft+0, mixed mode)
    The downloaded deb file is not required anymore and can be deleted to freeup space.

    Liberica Installation Folder
    The Liberica JDK is installin folder: /usr/lib/jvm/jdk-10-bellsoft-arm32-vfp-hflt
    Recommend to read the file readme.txt. The file release contains release version and module information.

    Setup Hints
    Performance GPU Memory

    To state again = ensure to set the Raspberry Pi GPU memory from default 64 to at least 256 or 512.
    If not the case, then a memory glGetError occurs:
    Code:
    Memory Error glGetError 0x505 or the B4J IDE Logs, like
    java.lang.NullPointerException
      at com.sun.prism.impl.ps.PaintHelper.initGradientTextures(PaintHelper.java:
    131)
      at com.sun.prism.impl.ps.PaintHelper.getGradientTexture(PaintHelper.java:
    141)
    Note:
    Be carefull using resources, i.e. a Label with a Big Font size consumes high amount of GPU memory.

    Error Message Failed to write to /sys/class/input/mice/uevent
    Message
    Code:
    Udev: Failed to write to /sys/class/input/mice/uevent – Check that you have permission to access input devices
    This message occurs when executing a JavaFX application on a Raspberry Pi using a user other than root, i.e. user pi.

    Cause
    JavaFX requires direct write access to device hardware.

    Solution Option 1
    Execute the application as sudo, i.e. sudo java -jar myjavafxapp.jar

    Solution Option 2
    Modify settings to grant write access to the devices all users that belongs to the input group.
    Edit the 99-com.rules file:
    Code:
    $sudo nano /etc/udev/rules.d/99-com.rules
    Add at the bottom:
    Code:
    SUBSYSTEM=="input*", PROGRAM="/bin/sh -c '\
     chown -R root:input /sys/class/input/*/ && chmod -R 770 /sys/class/input/*/;\
    '"
    Run the application without root: java -jar myjavafxapp.jar

    Application Test - B4J-Bridge
    To test the application developed on a device, i.e. Windows 10 PC, use the B4J Bridge.
    Install
    by creating a B4J folder, set as default, delete any previous versions, then download the B4J-Bridge:
    Code:
    mkdir /home/pi/b4j
    cd /home/pi/b4j                    
    rm b4j-bridge.jar
    wget http://www.b4x.com/b4j/files/b4j-bridge.jar
    Alternative to wget
    Transfer (via f.e. WinSCP) the B4J-Bridge from a development device to the RPi folder /home/pi/b4j.

    Run
    To run as root (do not forget esp, when using Pi4j) when logged in as user Pi:
    sudo <path to java> -jar b4j-bridge.jar

    If the path to java is set in the environment path, then call
    Code:
    sudo java -jar b4j-bridge
    It is useful to run the B4J-Bridge from a dedicated terminal, like f.e. from the development device using Putty.
    When doing so, the output of the running application can be watched.

    Application Test - Full Screen Mode
    On the Raspberry Pi, the JavaFX application runs in Full Screen Mode and captures all Linux input devices.
    When using VNC, the application is not visible - only on the monitor connected to the Raspberry Pi.
    There is no titlebar for forms & dialogs and Control-C is not working, means has to be catered for in the application.

    Autostart the B4J UI Application at Boot
    As an example application jar: dashboard.jar located in folder /home/pi/b4j

    Bash Script
    Create a bash script dashboard.sh in folder /home/pi/b4j
    Code:
    sudo nano dashboard.sh
    Content:
    Code:
    #!/bin/bash
    cd /home/pi/b4j
    sudo java -jar dashboard.jar
    Make the bash script executable:
    Code:
    sudo chmod +x dashboard.sh
    Edit autostart
    Code:
    nano ~/.config/lxsession/LXDE-pi/autostart
    add at file end:
    Code:
    @/home/pi/b4j/dashboard.sh
    Resulting in example:
    Code:
    @lxpanel --profile LXDE-pi
    @pcmanfm --desktop --profile LXDE-pi
    @xscreensaver -no-splash
    @
    point-rpi
    @/home/pi/b4j/dashboard.sh
    ... and reboot the Raspberry Pi to test if working.

    B4J UI Application Development Hints
    Merge Libraries
    When using additional libraries (i.e. Pi4J, SQLite ...), set the Project Attribute MergeLibraries:True.
    Example for a SQLite driver which is set by using a Conditional Symbol:
    Code:
    #Region Project Attributes
       
    #MainFormWidth: 1000
       
    #MainFormHeight: 800
       
    ' SQLite driver - located in the B4J core libraries folder - ensure to set the correct version
       #If PC
           #AdditionalJar: sqlite-jdbc-3.7.2
       #Else
           #AdditionalJar: sqlite-raspberry.jar
       
    #End If
       
    #MergeLibraries: True
       
    ' #CommandLineArgs: -l
    #End Region
    Application Close
    In the B4J application, ensure to implement a close button to exit the application as the generated application has not titlebar.
    Example of using a Close Button at the form bottom right and a Close [X] Button at the top right.
    Code:
    Sub Process_Globals
       
    Private btnClose As Button
       
    Private btnCloseX As Button
    ...

    Sub AppClose
       MainForm.Close
       
    ExitApplication
    End Sub

    ' Close the app using X Button top right corner
    Sub btnCloseX_Action
       AppClose
    End Sub

    ' Close the app using close button bottom right
    Sub btnClose_Action
       fx.Msgbox(MainForm, 
    "Hello World""Information")
       AppClose
    End Sub
    MsgBox
    The fx.MsgBox is displayed without titlebar and borders. The background color is white.
    Instead using the fx message boxes, consider to build an own class with a message box having a titlebar and other options.

    Snapshot
    To make a snapshot of a form, the jfxrt.jar (i.e. from JDK8) is required and must be added to the B4J additional libraries folder.
    Example:
    Code:
    'Make a snapshot of the mainform. The png file is stored in the dirapp folder.
    'Requires #AdditionalJar: jfxrt with jfxrt.jar located in the B4J additional libraries folder
    Sub FormSnapShot   'ignore
       Dim img As Image = MainForm.RootPane.Snapshot
       
    Dim Out As OutputStream = File.OpenOutput(File.DirApp, "snapshot.png"False)
       img.WriteToStream(Out)
       Out.Close
    End Sub
    Hint:
    Use the conditional snapshot to enable snapshots
    Code:
    #Region Project Attributes
       
    'Set the conditional snapshot to enable snapshots
       #If snapshot
           'The jar jfxrt is required for the class SwingFXUtils to make a screenshot of the mainform when running on the RPi.
           'This to avoid runtime error: java.lang.NoClassDefFoundError: javafx/embed/swing/SwingFXUtils
           'Copy c:\Program Files (x86)\Java\jdk8\jre\lib\ext\jfxrt.jar to the B4J additional libraries folder.
           'Note: Check your JDK path prior copying to the B4J additional library folder.
           #AdditionalJar: jfxrt
       
    #End If
    #End Region
    Code:
    Sub AppClose_Action
       
    #If snapshot
           FormSnapShot("snapshot.png")
       
    #End If
       MainForm.close
       
    ExitApplication
    End Sub
    Maximize Screen
    As mentioned, the application runs in full screen.
    When setting the Project Attributes MainFormWidth and MainFormHeight to a certain value, which is smaller then the full screen size, the form is displayed as sub window from the full screen.
    Recommend to set the form to full screen.
    Example sub routine setting to full screen with an offset.
    The offset was used to handle an openJDK error, where the cursor disappears when moving to the far right of the form. In newer JDK versions, this error did not show up anymore.
    Code:
    ' Set the form to fill the screen with an offset
    Sub SetFormFillScreenOffset(frm As Form, offset As Int)   'ignore
       Dim ps As Screen = fx.PrimaryScreen
       frm.WindowLeft = ps.MinX + offset
       frm.WindowWidth = ps.MaxX - frm.WindowLeft - offset
       frm.WindowTop = ps.MinY + offset
       frm.WindowHeight = ps.MaxY - frm.WindowTop - offset
    End Sub
    Code:
    'Set the form to fill the screen with an offset - comment if want to use the window dimensions defined in the project attributes
    SetFormFillScreenOffset(MainForm, 50)
    Java Version
    If want to know or display the Java version on the Raspberry Pi:
    Code:
    Private lblStatus As Label
    lblStatus.Text = 
    $"Java ${GetSystemProperty("java.version","0.0.0_00")}"$
    Raspberry Pi 7" Touchscreen
    The sample applications have been tested esp. on the Raspberry Pi 7" touchscreen with dimensions 800*480.
    In the B4J Visual Designer, defined a new Variant 800*480,scale=1 (160dpi).
    Layout used for the samples:
    Code:
    [Top Pane [Label Title][Button CloseX] ]
    [CONTENT]
    [Bottom 
    Pane [Label Info][Button Close] ]
    View Properties
    Code:
    Top Pane=Parent:Main,Hor Anchor:Both,Ver Anchor:Top,Left:5,Top:5,Right:5,Height:50
    Label Title=Parent:Top Pane,Hor Anchor:Both,Ver Anchor:Both,Left:10,Top:10,Right:10,Bottom:10
    Button CloseX:Parent:Top Pane,Hor Anchor:Right,Ver Anchor:Both,Right:10,Top:0,Width;50,Bottom:0. Used Fontawesome close icon Chr(0xF2D4) with size 18.
    Code:
    Bottom Pane=Parent:Main,Hor Anchor:Both,Ver Anchor:Bottom,Left:5,Top:5,Right:5,Height:50
    Label Info=Parent:Bottom Pane,Hor Anchor:Both,Ver Anchor:Both,Left:10,Top:10,Right:10,Bottom:10
    Button CloseX:Parent:Bottom Pane,Hor Anchor:Right,Ver Anchor:Both,Right:20,Top:10,Width;100,Bottom:10
    Application Samples
    Build a few sample B4J UI applications - Download B4J source code.
    As mentioned, tested the samples esp. with the 7" touchscreen.

    IMPORTANT: For tests, please check if the conditional symbol snapshot is set and take out as required - used for making snapshots.

    01-HelloWorld - The classic one to start with
    02-LEDSwitch - Switch an LED connected to GPIO ON/OFF
    03-LCDClock - Simple label showing time
    04-Look4HowViewer - View Look4How databases (more)
    06-CPU-Temperature-Dashboard - Display & log the Raspberry CPU temperature (Gauge)
    07-HomeAutomationDashboard - Weather information displayed in Gauges and logged in a listview on a 7" touchscreen
    99-WebView - Currently not supported by Liberica JDK v10. Awaiting update information.

    [​IMG]
     
    Last edited: May 13, 2018
Loading...