Monday, November 25, 2013

Enzo part I

Hi everyone,

As you might know I've started another JavaFX controls library named Enzo which you can find on github.
This project started as a playground for JDK8 and JavaFX8 and in the meantime it contains some controls that I would like to share with you.
So this is the first post of a series about the Enzo controls. The idea is to explain one control with each post and because it's my favourite control I will start with the Lcd control.

The Lcd control can be found in the package: eu.hansolo.enzo.lcd

If you instantiate a Lcd control you will get something like this...



This is the simplest version of the Lcd control only showing a value. The control offers many different features and if everything is enabled it will look like this...





As you can see there are different kind of symbols and text fields available.
On the next screenshot you will find the name of each feature...




Most of the above features could switched on/off (except the backgroundText which depends on the used valueFont). Because all controls in Enzo will come with a Builder (I liked the builders so I decided to add them to my controls) the code to instantiate the full blown lcd will look like this...

Lcd lcd = LcdBuilder.create()
                    .prefWidth(480)
                    .prefHeight(192)  
                    .styleClass(Lcd.STYLE_CLASS_STANDARD)
                    .backgroundVisible(true)                     
                    .value(42)
                    .foregroundShadowVisible(true)
                    .crystalOverlayVisible(true)
                    .title("Title")
                    .titleVisible(true)
                    .batteryVisible(true)
                    .signalVisible(true)
                    .alarmVisible(true)
                    .unit("°C")
                    .unitVisible(true)
                    .decimals(2)
                    .minMeasuredValueDecimals(2)
                    .minMeasuredValueVisible(true)
                    .maxMeasuredValueDecimals(2)
                    .maxMeasuredValueVisible(true)
                    .formerValueVisible(true)
                    .threshold(26)
                    .thresholdVisible(true)
                    .trendVisible(true)
                    .trend(Lcd.Trend.RISING)
                    .numberSystemVisible(true)
                    .lowerRightTextVisible(true)              
                    .valueFont(Lcd.LcdFont.LCD)
                    .animated(true)

                    .build();

As you can see in the code above there is a styleClass method in the builder where you can define the visual appearance of the Lcd control. And because there are so many nice Lcd displays out there I've tried to cover as many as I've found. 
To give you an overview over all available styles I created another screenshot for you...



As you can see there are a lot of different styles available and all of them are defined in CSS. You will find more realistic versions and also some flat ui styled ones.
In case you don't want to use a style at all you can simply switch of the background by calling setBackgroundVisible(false). With this feature you could use the Lcd also on your own backgrounds which sometimes might be useful.
You will also find features like the signal, trend, alarm or battery indicator which you can switch on or off by calling 

  • setSignalVisible(true/false
  • setTrendVisible(true/false)
  • setAlarmVisible(true/false)
  • setBatteryVisible(true/false)

The signal, trend and battery indicator also have getters and setters to set their value. So to set the battery to another value you can call

  • setBatteryCharge(double 0...1)

and for the signal indicator please call

  • setSignalStrength(double 0...1)

The trend indicator has 6 different states that you can call, the states are

  • UP
  • RISING
  • STEADY
  • FALLING
  • DOWN
  • UKNOWN

and the method to set one of these is

  • setTrend(Lcd.Trend.STATE)

Keep in mind that you have to take care about the trend which means you have to check whether it's rising or falling, so you can implement your own algorithm to calculate the trend.

You have 5 different fonts available to visualize the main value of the Lcd control. The available fonts are

  • Lcd.LcdFont.STANDARD
  • Lcd.LcdFont.LCD
  • Lcd.LcdFont.DIGITAL
  • Lcd.LcdFont.DIGITAL_BOLD
  • Lcd.LcdFont.ELEKTRA

which will look like this


Lcd.LcdFont.DIGITAL

Lcd.LcdFont.DIGITAL_BOLD

Lcd.LcdFont.ELEKTRA

Lcd.LcdFont.LCD

Lcd.LcdFont.STANDARD
If you use the Lcd control to measure values in a longer interval (> 2 sec) you can use the animation feature which will count the value from the current value to the new value in the time that you specified with setAnimationDuration(double duration) in ms. This is useful if you for example measure the temperature every 5 minutes you could set the animation duration to 60000 ms which will then slowly increase/decrease the value to the new measured value within a minute. But if you measure values more quickly (interval < 2 sec) you should switch off the animation by calling setAnimated(false). This will directly set the lcd value to the new value.

Another maybe useful feature is the ability to blink the value of the Lcd control by calling setBlinking(true). This feature can be used to indicate that a threshold was exceeded or simply to grab the attention of the user.

The Lcd control supports three different number systems that you can use which are


  • Lcd.NumberSystem.DECIMAL
  • Lcd.NumberSystem.HEXADECIMAL
  • Lcd.NumberSystem.OCTAL


which will display the current value in the choosen number system.
The lower right text can therefor be used to display the current number system by calling setNumberSystemVisible(true which will override the setLowerRightText("YOUR TEXT") method. Here are examples for the different modes


Lcd.NumberSystem.DECIMAL


Lcd.NumberSystem.HEXADECIMAL

Lcd.NumberSystem.OCTAL
It is also possible to use the Lcd control as a simple text display by enabling the text mode with setTextMode(true).
There is no scrolling or animation implemented for the text but this might come in future releases of the control.
Keep in mind that the text mode will not work with the Lcd.LcdFont.LCD because this is a 7-Segment font which has no characters.
Here are some examples






You can also use the text mode in combination with all the other features as on the following picture



I hope I covered most of the features of the Lcd control and if you have a special need for an additional feature you could either let me know and hope that I'll find some time to implement it or you can fork the project on bitbucket and do it yourself... :)

If you are interested in the sources you can find them on bitbucket at

https://bitbucket.org/hansolo/enzo/wiki/Home

That's it for today...so keep coding...

4 comments:

  1. as far i as i keep your coding under stress test (i have 4 lcds changing value every ten seconds) once in an hour i see the following exception (jdk 1.8.66).


    Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at com.sun.javafx.text.PrismTextLayout.addTextRun(Unknown Source)
    at com.sun.javafx.text.GlyphLayout.addTextRun(Unknown Source)
    at com.sun.javafx.text.GlyphLayout.breakRuns(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.buildRuns(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.layout(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.ensureLayout(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.getBounds(Unknown Source)
    at javafx.scene.text.Text.getLogicalBounds(Unknown Source)
    at javafx.scene.text.Text.impl_computeLayoutBounds(Unknown Source)
    at javafx.scene.Node$12.computeBounds(Unknown Source)
    at javafx.scene.Node$LazyBoundsProperty.get(Unknown Source)
    at javafx.scene.Node$LazyBoundsProperty.get(Unknown Source)
    at javafx.scene.Node.getLayoutBounds(Unknown Source)
    at eu.hansolo.enzo.lcd.skin.LcdSkin.updateBackgroundText(LcdSkin.java:562)
    at eu.hansolo.enzo.lcd.skin.LcdSkin.updateLcd(LcdSkin.java:628)
    at eu.hansolo.enzo.lcd.skin.LcdSkin.handleControlPropertyChanged(LcdSkin.java:342)
    at eu.hansolo.enzo.lcd.skin.LcdSkin.lambda$registerListeners$34(LcdSkin.java:294)
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(Unknown Source)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(Unknown Source)
    at javafx.beans.property.DoublePropertyBase.fireValueChangedEvent(Unknown Source)
    at javafx.beans.property.DoublePropertyBase.markInvalid(Unknown Source)
    at javafx.beans.property.DoublePropertyBase.set(Unknown Source)
    at eu.hansolo.enzo.lcd.Lcd$2.interpolate(Lcd.java:330)
    at javafx.animation.Transition.impl_playTo(Unknown Source)
    at javafx.animation.AnimationAccessorImpl.playTo(Unknown Source)
    at com.sun.scenario.animation.shared.SingleLoopClipEnvelope.timePulse(Unknown Source)
    at javafx.animation.Animation.impl_timePulse(Unknown Source)
    at javafx.animation.Animation$1.lambda$timePulse$25(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at javafx.animation.Animation$1.timePulse(Unknown Source)
    at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(Unknown Source)
    at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(Unknown Source)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(Unknown Source)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(Unknown Source)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

    i do not understand if it is a jdk bug or an enzo bug.

    ReplyDelete
    Replies
    1. It seems to be a bug in Enzo, could you send me the code you use for testing? You might want to file an issue at bitbucket.
      Cheers,
      Gerrit

      Delete
  2. Hi Gerrit,
    First of all, great job!!
    I like so much of your controls libraries!
    I'd like to know, if can I use the LCD unit on the top of the number, for example as a exponent (3³) or a symbol like (180º) degrees.

    Best regards.

    Ruan

    ReplyDelete
    Replies
    1. Hi Ruan,
      The unit is a simple string so you should be able to set it to whatever you like

      Delete