Tuesday, April 14, 2015

JavaFX : Using Shapes To Create Your Own Icons

If you are like me you are always on the lookout for great icons for your applications. I always seem to find options that are very close but not quite right. If the design looks good then the color is wrong, or if the color and design are great the icon isn't available in the size I need. As a general rule I do not go into Photoshop or any other graphics tools and create or modify items like icons as I do not have an eye for good design. That brings us to JavaFX shapes and how you can leverage built in objects to generate great looking sharp icons or images to use in your applications that are generated from code so no external resources are required.

Below is an example of a play, pause, stop, and checkmark icon I created for a JavaFX application which I will be releasing later this year!


The code for this project can be found on github: https://github.com/dtbell99/JavaFXShapeIcons

FXML Markup:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.shape.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>


<AnchorPane id="AnchorPane" prefHeight="328.0" prefWidth="395.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.40" fx:controller="com.broadlyapplicable.javafxexamples.shapes.icons.CustomController">
   <children>
      <VBox fx:id="vbox" layoutX="70.0" layoutY="51.0" prefHeight="328.0" prefWidth="395.0" spacing="75.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="25.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="25.0" />
   </children>
</AnchorPane>


Controller:

package com.broadlyapplicable.javafxexamples.shapes.icons;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Polyline;
import javafx.scene.shape.Rectangle;

public class CustomController implements Initializable {
    
    @FXML
    private VBox vbox;
    
    private static final String GREEN = "#68C953";
    private static final String RED = "#CF3E3E";
    private static final String YELLOW = "#EDAD18";
    private static final String BLUEGREEN = "#22BDBD";
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        vbox.getChildren().add(getPlayIcon());
        HBox hbox = new HBox(5);
        hbox.getChildren().add(getHalfPause());
        hbox.getChildren().add(getHalfPause());
        vbox.getChildren().add(hbox);
        vbox.getChildren().add(getStopIcon());
        vbox.getChildren().add(getCompletedIcon());
    }    
    
    private Polyline getCompletedIcon() {
        Polyline polygon = new Polyline();
        polygon.getPoints().addAll(new Double[]{
            0.0, 100.0, 40.0, 150.0, 80.0, 0.0
        });        
        polygon.setStroke(Paint.valueOf(BLUEGREEN));
        polygon.setStrokeWidth(15.0);
        return polygon;
    }
    
    private Polygon getPlayIcon() {
        Polygon polygon = new Polygon();
        polygon.getPoints().addAll(new Double[]{
            0.0, 0.0,
            0.0, 100.0,
            75.0, 50.0});
        
        polygon.setFill(Paint.valueOf(GREEN));
        return polygon;
    }
    
    private Rectangle getHalfPause() {
        Rectangle rectangle = new Rectangle();
        rectangle.setHeight(75);
        rectangle.setWidth(30);
        rectangle.setFill(Paint.valueOf(YELLOW));
        return rectangle;
    }
    
    private Rectangle getStopIcon() {
        Rectangle rectangle = new Rectangle();
        rectangle.setHeight(65);
        rectangle.setWidth(65);
        rectangle.setFill(Paint.valueOf(RED));
        return rectangle;
    }
    
}