JavaFX button with svg

2019-04-01 17:47发布

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.

1条回答
放荡不羁爱自由
2楼-- · 2019-04-01 18:21

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;
}
查看更多
登录 后发表回答