Validation in java (javafx)

Validation is one thing that’s missing from the core javafx framework. To fill in this gap there is already a 3rd party validation library that’s present in controlsfx. However there’s one issue I have with it: it wasn’t created with FXML in mind. That’s not to say it isn’t a good library, it just misses this detail and for me this is a no go. Because of that I decided to create my own validation framework: FXValidation.

How it works

To show you how FXValidation works let’s start from the bottom up, by showing you an example of what an FXML file might look like when using this library. This is a simple example of a login screen where the user needs to enter both an user name and a password:

<Label>
  <text>User Name:</text>
</Label>
<TextField fx:id="userName" id="userName"></TextField>
<Label>
  <text>Password:</text>
</Label>
<PasswordField fx:id="password" id="password"></PasswordField>

<Button text="Submit" onAction="#submitPressed"></Button>

<fx:define>
  <RequiredField fx:id="requiredField1" >
    <srcControl>
      <fx:reference source="userName"></fx:reference>
    </srcControl>
  </RequiredField>
  <RequiredField fx:id="requiredField2" >
    <srcControl>
      <fx:reference source="password"></fx:reference>
    </srcControl>
  </RequiredField>
</fx:define>

<ErrorLabel message="Please enter your username">
  <validator>
    <fx:reference source="requiredField1"></fx:reference>
  </validator>
</ErrorLabel>
<ErrorLabel message="Please enter your password">
  <validator>
    <fx:reference source="requiredField2"></fx:reference>
  </validator>
</ErrorLabel> 

On the beginning of the FXML snippet I define a textfield and password field for entering the login details. Other than that there’s also a submit button so the user may send the login information to the system. After that comes the interesting part. First we define a couple of validators of type RequiredField. This validators, check whether the input in question is empty and if so they store that the validation has errors in a flag. There’s also other types of validators built-in the FXValidation framework but we’ll get to that in a bit. Finally we define a couple of ErrorLabels. This are nodes that implement IValidationDisplay, any class that implements this interface is a class whose purpose is to display information to the user whenever there is an error in the validation process. Currently there is only one of this classes in the framework: the ErrorLabel. Finally we need to call validation when the user clicks the submit button, this is done in the controller on the submit method:

public void submitPressed(ActionEvent actionEvent) {
  requiredField1.eval();
  requiredField2.eval();
}

This will trigger validation for the validators that we have defined. If there are errors the ErrorLabels will display the error message that was defined in them. There’s also one extra thing the validators do: they add in the css style class of “error” to every control that is in error after the validation process has taken effect. This allows the programmer to style the controls differently using css whenever this controls have the error class appended to them. The programmer can check for errors in the validation process by checking the property hasErrors in the validators.

And here’s our example in action:

validation

The details

From what I’ve shown you above we can see that there are basically 2 types of classes involved:

  • The validator: takes care of checking if the target control (srcControl) conforms to the validation rule. If not it appends the “error” style class to target control sets its hasErrors property to true. All validators extend from ValidatorBase.
  • The error display information: this takes care of informing the user what went wrong with the validation, it might be that the field is required, the fields content doesn’t have the necessary number of characters, etc. All this classes implement IValidationDisplay.

In the library there are currenctly 3 validators and only one error “displayer” which is ErrorLabel. The validators are the following:

  • RequiredField: Checks whether the target control (srcControl) has content, if it doesn’t it gives an error.
  • CardinalityValidator: Checks whether the target control (srcControl) has at least a min number of characters and a maximum of max number of characters.
  • RegexValidator: Checks the content of the target control (srcControl) against a given regular expression

And that’s it.

I’d love to collaborate with ControlsFX or if someone else wants to contribute fell free to do so. So that we can achieve the definitive validation framework.

Metro style Slider for java (JMetro)

One thing that’s missing from java 8 javafx slider is the fill that comes from the beginning of the slider to the thumb. You can see this in windows 8 as well as several other operating systems: ios 6 and 7, android, etc.

So by using only CSS, it is not possible to style the fill of the slider, to accomplish this you’d have to create your own skin to use with the slider. And that’s exactly what I did by creating the “FilledSliderSkin”.

With this skin set on the slider you can style its fill color, like so:

.slider .fill {
 -fx-background-color: #00828b;
 -fx-padding: 0.333333em; 
}
.slider .fill:hover {
 -fx-background-color: #219297;
}

You can use this skin to achieve the styles of ios 6, 7 and android sliders.

And here are the screenshots of the slider with a metro style:

Slider - Dark Theme

Slider – Dark Theme

Slider - Light Theme

Slider – Light Theme

Metro style ProgressBar for java (JMetro)

It’s been a while since my last post..

I’ve been doing some tweaks here and there but nothing too significant for a blog post. Unfortunately haven’t had much time to spend on side projects, hopefully I’ll have time to style a new control every other week or so..

So, this time it’s the ProgressBar (also some other tweaks to the existing styles). Enjoy!

ProgressBar (dark theme)

ProgressBar – Dark Theme

ProgressBar (light theme)

ProgressBar – Light Theme

 

 

 

Metro style Password Box for java (JMetro)

The metro style password field is very similar to the Text Box (Text Input Field) in its design. The look is very similar and it also has a button to the far right of the control.

passwordBoxWindows8

Password Box with the password masked

 

This time instead of clearing the field, pressing the button will reveal the text you’ve just entered which is by default masked. This is useful, especially for long passwords and while entering the password through touch instead of a keyboard, which is less error prone.

passwordBoxWindows8-buttonPressed

Password Box with the password revealed

 

So here are the screenshots of the light and dark theme of the Password Box JMetro skin implementation:

Password Box - Light theme

Password Box – Light theme

Password Box - Dark theme

Password Box – Dark theme

Skinning in Java8 (JavaFX8)

There has been some changes in JavaFX8 regarding skinning, the most relevants of which are the new CSS API that allows you to create new CSS properties and pseudo-classes for your controls and the Skin class which has become public.

Using CSS you can change a lot of the appearance of a control, but there is only so much you can achieve with CSS and this is where the Skin class comes in. A quick look at the architecture of controls from “UI Controls Architecture”:

Controls follow the classic MVC design pattern. The Control is the “model”. It contains both the state and the functions which manipulate that state. The Control class itself does not know how it is rendered or what the user interaction is. These tasks are delegated to the Skin (“view”), which may internally separate out the view and controller functionality into separate classes, although at present there is no public API for the “controller” aspect. mvc

Like was mentioned there is still some aspects of Skinning that are not yet public API and that is the Behavior class, however, with the current state of things, you can already do a lot.

Since Java8 is not in G.A. status (full finished version) yet, there is still a considerable lack of documentation regarding the API, which brings me to my latest post on JMetro, at that time I was mistakenly under the impression that you had to extend a control in order to change its reference to the skin class, that’s why I created the ErasableTextField. However, as I later learned, you can change the skin class of a control just through CSS, like this:

.text-field{
    -fx-skin: "jfxtras.styles.jmetro8.MetroTextFieldSkin";
}

The “text-field” style class is assigned to TextField, so when the “-fx-skin” CSS property value is changed the reference to the skin class that is to be used with this control changes. So the ErasableTextField class is no longer necessary and has been removed from JMetro.

I find this design very interesting! As you can see the Skins are completely decoupled from the controls, all you have to do is assign a stylesheet to a scene without touching any of the code in your app and the look and feel of your application can change radically – like for instance JMetro Textfield skin adds a clear button that shows up whenever there is text inside:

jmetro-textbox

JMetro adds a clear button to TextField

DateAxis and XYBarChart update

Just the other day Gerrit Grunwald (@hansolo_) tweeted he made a DateAxis which supports JSR310 (date/time) api, and which is based on my work and also on Christian Schudt and Diego Cirujano-Cuesta work (they created a DateAxis which accepts DateTime). He later added that he would eventually create a blog post about it if he had time (you should stay tuned his posts are usually high quality). This reminded me that a blog post about my DateAxis and XYBarChart is long overdue since I’ve made a lot of changes since my last posts on the subject. Besides the changes I also wanted to explain my implementation of the DateAxis and why I’m sticking with the design (code design not artistic design) choices I’ve made.

Design decisions while creating DateAxis

While creating DateAxis I had two choices, either extend from Axis or from ValueAxis. Extending from Axis would allow me to accept DateTime or the new date formats from JSR310, while extending from ValueAxis would guarantee the presence of methods like setLowerBound and setUpperBound which would allow a user to filter or zoom in on specific dates, a fairly common use case, but would mean programmers would first need to convert the date to a number before adding it to the chart. Of course you can add filtering methods yourself while extending from Axis but a component that does zooming on charts and is expecting a ValueAxis (which guarantees setUpperBound and setLowerBound) wouldn’t work with that implementation.

Even though at first I was thinking that extending from Axis would be better, I’m now more convinced that the current solution – extending from ValueAxis, is a better one, for the reasons expressed earlier, and the draw back of having to convert the date to a number isn’t such a big thing.

I think it would be best if the JavaFX charts API would allow one to separate the position of a value in an axis from the value itself I think it would be best for setLowerBound and setUpperBound to be mandatory methods on Axis, but has things are right now you have to take in consideration the two drawbacks mentioned earlier before starting to implement a new axis.

Changes made to DateAxis and XYBarChart

I’m afraid I’ve probably forgotten about most of the changes I’ve made, anyway here’s what I recall:

DateAxis

  1. After changing range (by zooming in for instance) the tick marks interval stayed the same. Now they are recalculated.
  2. Added a bigger set of tick ranges to accommodate a higher range of dates.

XYBarChart (this previous post explains what this is)

  1. On some occasions depending on the data you add to the chart, it may not render any bars even though there is data to be displayed. This is a bug that exists in javafx BarChart and was passed on to this chart since there was some copying of code.

Today, I also added one more enhancement to the DateAxis which was on the pipeline of changes I wanted to make. Basically the format of the dates will change depending on the range of values that is being shown: for instance, if each tick mark represents more than a month than only the month and year of that tick mark is shown otherwise the day, month and year is displayed. A similar thing happens if the range of tick marks is bigger than one year, in that case only the corresponding year is shown. The following pictures show the before and after this change.

beforeChange8

XYBarChart with a DateAxis – before change

afterChange8

XYBarChart with a DateAxis – after change

This is just a small detail that makes for an easier scanning of the chart by the user.

If you want to join me, in adding more features to the charts API, you are welcome. My eventual objective would be for this to be integrated in the JavaFX API (at least the DateAxis) although I don’t know if that would be possible.