Fork us on GitHub

It's Full Of Stars & Terse Commands

Rating widget and shorter syntax for commands
It's Full Of Stars & Terse Commands

It's Full Of Stars & Terse Commands

A very common UI pattern is the 5 star ranking system. Up until recently we always had the same answer when developers asked us how to implement it: "Use toggle buttons (CheckBox)".

This is still not a bad answer but we think there is a "better" simpler way to do this thru the Slider which was effectively designed with this usage in mind.

The best way to do that is to just create two images with all 5 stars full and with all 5 stars empty and assign this to the Slider/SliderFull UIID’s. Keep in mind that you need to apply both to the selected and unselected states of the UIID’s.

You can change the UIID of slider itself e.g. to something like "Stars" at which point the UIID’s will be Stars & StarsFull.

This will allow your users to click/drag to select the number of stars. The code below uses the star material icon to generate something like this on the fly without any resources.

We enclose the slider in a FlowLayout to prevent it from growing. This is because I chose the stars to be tiled instead of aligned (like we could if we used an image). So if the component will grow it won’t have the right feel. Enclosing the component in a FlowLayout is an old trick to prevent components from growing beyond their preferred size.
private void initStarRankStyle(Style s, Image star) {

private Slider createStarRankSlider() {
    Slider starRank = new Slider();
    Font fnt = Font.createTrueTypeFont("native:MainLight", "native:MainLight").
            derive(Display.getInstance().convertToPixels(5, true), Font.STYLE_PLAIN);
    Style s = new Style(0xffff33, 0, fnt, (byte)0);
    Image fullStar = FontImage.createMaterial(FontImage.MATERIAL_STAR, s).toImage();
    Image emptyStar = FontImage.createMaterial(FontImage.MATERIAL_STAR, s).toImage();
    initStarRankStyle(starRank.getSliderEmptySelectedStyle(), emptyStar);
    initStarRankStyle(starRank.getSliderEmptyUnselectedStyle(), emptyStar);
    initStarRankStyle(starRank.getSliderFullSelectedStyle(), fullStar);
    initStarRankStyle(starRank.getSliderFullUnselectedStyle(), fullStar);
    starRank.setPreferredSize(new Dimension(fullStar.getWidth() * 5, fullStar.getHeight()));
    return starRank;
private void showStarPickingForm() {
    Form hi = new Form("Star Slider", new BoxLayout(BoxLayout.Y_AXIS));

In this code you will notice we allow selecting a value between 0 & 10 where 10 is really 5 stars. This allows us to pick values like 4.5 stars and just divide the actual value. However, most ranking systems don’t allow a value below 1 star. To solve this you can just use a Label to represent the first star and use a the Slider for the remaining 4 stars. In which case the values would be between 0 - 8.

Terse commands

I love lambdas. I wasn’t a fan before they were introduced but they grew on me and made me a convert.

One of the annoyances I had with Codename One was with using Command syntax which forced me to fallback to pre-lambda code for practically everything as Command is a class and not a single method interface. This bothered me enough to do something about it so now we have ActionListener versions of many Command API’s.

These all redirect to the Command.create(String,Image,ActionListener) method which effectively creates a Command with the given details for the given action listener. So instead of writing code like this:

form.getToolbar().addToSideMenu(new Command("My Command") {
     public void actionPerformed(ActionEvent ev) {

I can write this:

form.getToolbar().addToSideMenu(Command.create("My Command", null, (ev) -> {

And to make things even simpler I created helper methods that do that implicitly in Toolbar and Form:

form.getToolbar().addToSideMenu("My Command", null, (ev) -> {

Notice that the version of this method that accepts a the action listener also returns the created Command instance which might be useful if you want to do something with the command later on (e.g. remove it). So this should work:

Command cmd = form.getToolbar().addToSideMenu("My Command", null, (ev) -> {
Share this Post:

Posted by Shai Almog

Shai is the co-founder of Codename One. He's been a professional programmer for over 25 years. During that time he has worked with dozens of companies including Sun Microsystems.
For more follow Shai on Twitter & github.