Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX button with svg

I have this SVG:

M421.985,229.833L217.847,25.981c-7.235-7.238-16.94-13.374-29.121-18.416C176.541,2.522,165.407,0,155.318,0H36.547 C26.648,0,18.083,3.619,10.85,10.848C3.617,18.081,0.002,26.646,0.002,36.545v118.771c0,10.088,2.519,21.219,7.564,33.404   s11.182,21.792,18.417,28.837L230.118,421.98c7.043,7.043,15.602,10.564,25.697,10.564c9.89,0,18.558-3.521,25.98-10.564   l140.186-140.47c7.043-7.046,10.561-15.604,10.561-25.693C432.542,245.919,429.024,237.258,421.985,229.833z M117.202,117.201   c-7.142,7.138-15.752,10.709-25.841,10.709c-10.085,0-18.699-3.571-25.837-10.709c-7.138-7.139-10.706-15.749-10.706-25.837   c0-10.089,3.568-18.702,10.706-25.837c7.139-7.139,15.752-10.71,25.837-10.71c10.089,0,18.702,3.571,25.841,10.71   c7.135,7.135,10.706,15.749,10.706,25.837C127.908,101.452,124.341,110.062,117.202,117.201z

It's copied from here: http://www.flaticon.com/free-icon/tag-black-shape_25679#term=label&page=1&position=56

I need to have some component (most likely a button), that has this shape, that has size 24x24 and that has some effect on hover (like gradient).

Is that even possible, in JavaFX? CSS border properties don't work with scaling, SVG can't be scaled, I just can't achieve all of these requirements.

like image 466
Patrik Bak Avatar asked Nov 22 '16 23:11

Patrik Bak


1 Answers

You can use the SVG as shape for a Region. Depending on your needs this Region could be the Button itself or a graphic assigned to it:

Button only

Button btn = new Button();
btn.getStyleClass().add("icon-button");
btn.setPickOnBounds(true);

CSS stylesheet

.icon-button {
    -icon-paint: red;
    -fx-background-color: -icon-paint;
    -size: 24;
    -fx-min-height: -size;
    -fx-min-width: -size;
    -fx-max-height: -size;
    -fx-max-width: -size;

    -fx-shape: "M421.985,229.833L217.847,25.981c-7.235-7.238-16.94-13.374-29.121-18.416C176.541,2.522,165.407,0,155.318,0H36.547 C26.648,0,18.083,3.619,10.85,10.848C3.617,18.081,0.002,26.646,0.002,36.545v118.771c0,10.088,2.519,21.219,7.564,33.404   s11.182,21.792,18.417,28.837L230.118,421.98c7.043,7.043,15.602,10.564,25.697,10.564c9.89,0,18.558-3.521,25.98-10.564   l140.186-140.47c7.043-7.046,10.561-15.604,10.561-25.693C432.542,245.919,429.024,237.258,421.985,229.833z M117.202,117.201   c-7.142,7.138-15.752,10.709-25.841,10.709c-10.085,0-18.699-3.571-25.837-10.709c-7.138-7.139-10.706-15.749-10.706-25.837   c0-10.089,3.568-18.702,10.706-25.837c7.139-7.139,15.752-10.71,25.837-10.71c10.089,0,18.702,3.571,25.841,10.71   c7.135,7.135,10.706,15.749,10.706,25.837C127.908,101.452,124.341,110.062,117.202,117.201z";
}

.icon-button:hover {
    -icon-paint: linear-gradient(to bottom, red, black);
}

Button with graphic

Button btn = new Button();
btn.getStyleClass().add("icon-button");
btn.setPickOnBounds(true);

Region icon = new Region();
icon.getStyleClass().add("icon");
btn.setGraphic(icon);

CSS stylesheet

.icon-button {
    -icon-paint: red;
    -fx-content-display: graphic-only;

    -icon-paint: red;
}

.icon-button:hover {
    -icon-paint: linear-gradient(to bottom, red, black);
}

.icon-button .icon {
    -fx-background-color: -icon-paint;
    -size: 24;
    -fx-min-height: -size;
    -fx-min-width: -size;
    -fx-max-height: -size;
    -fx-max-width: -size;

    -fx-shape: "M421.985,229.833L217.847,25.981c-7.235-7.238-16.94-13.374-29.121-18.416C176.541,2.522,165.407,0,155.318,0H36.547 C26.648,0,18.083,3.619,10.85,10.848C3.617,18.081,0.002,26.646,0.002,36.545v118.771c0,10.088,2.519,21.219,7.564,33.404   s11.182,21.792,18.417,28.837L230.118,421.98c7.043,7.043,15.602,10.564,25.697,10.564c9.89,0,18.558-3.521,25.98-10.564   l140.186-140.47c7.043-7.046,10.561-15.604,10.561-25.693C432.542,245.919,429.024,237.258,421.985,229.833z M117.202,117.201   c-7.142,7.138-15.752,10.709-25.841,10.709c-10.085,0-18.699-3.571-25.837-10.709c-7.138-7.139-10.706-15.749-10.706-25.837   c0-10.089,3.568-18.702,10.706-25.837c7.139-7.139,15.752-10.71,25.837-10.71c10.089,0,18.702,3.571,25.841,10.71   c7.135,7.135,10.706,15.749,10.706,25.837C127.908,101.452,124.341,110.062,117.202,117.201z";
}

Results

The Button with a graphic with the shape is shown left, the Button with the shape applied directly to it is shown right.

Edit: to combine multiple paths you could combine several SVGPaths

Update

For more complex icons SVGPaths could be combined to be used as graphic for a button:

private static SVGPath createPath(String d, String fill, String hoverFill) {
    SVGPath path = new SVGPath();
    path.getStyleClass().add("svg");
    path.setContent(d);
    path.setStyle("-fill:" + fill + ";-hover-fill:"+hoverFill+';');
    return path;
}
Group svg = new Group(
        createPath("M0,0h100v100h-100z", "red", "darkred"),
        createPath("M20,20h60v60h-60z", "blue", "darkblue")
);

Bounds bounds = svg.getBoundsInParent();
double scale = Math.min(20/bounds.getWidth(), 20 / bounds.getHeight());
svg.setScaleX(scale);
svg.setScaleY(scale);

Button btn = new Button();
btn.setGraphic(svg);
btn.setMaxSize(30, 30);
btn.setMinSize(30, 30);
btn.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

CSS

.button .svg {
    -fx-fill: -fill;
}

.button:hover .svg {
    -fx-fill: -hover-fill;
}
like image 140
fabian Avatar answered Sep 19 '22 01:09

fabian