JavaFX 8 - Add a graphic to a TitledPane on the right side - java
I want to add a little icon to the title of a TitledPane. Therefore I set an empty title and add a HBox containing a Label and a ImageView as graphic. In this way the icon is shown close to the end of the text. I want it to be shown always next to the right border of the TitledPane.
How can I do this?
I also tried to use a BorderPane and add the Label to the center and the ImageView to the right, but the BorderPane doesn't get the maximum size of the TitledPane.
So I tried to set MaxWidth to Max-Value, but this didn't help
Does anybody know what to do?
**EDIT: ** The "custom" control I created will be initialized within a method called in stage.setOnShown.
public class CustomTitledPane extends TitledPane {
private Image alert;
private Image registered;
private Image deleted;
private ImageView img;
public CustomTitledPane(String titleText, Node node) {
super(titleText, node);
setAnimated(true);
setCollapsible(true);
img = new ImageView();
img.setFitHeight(10d);
img.setPreserveRatio(true);
img.setSmooth(true);
setGraphic(img);
setContentDisplay(ContentDisplay.RIGHT);
// apply css and force layout of nodes
applyCss();
layout();
// title region
Node titleRegion = lookup(".title");
// padding
Insets padding = ((StackPane) titleRegion).getPadding();
// image width
double graphicWidth = img.getLayoutBounds().getWidth();
// arrow
double arrowWidth = titleRegion.lookup(".arrow-button")
.getLayoutBounds().getWidth();
// text
double labelWidth = titleRegion.lookup(".text").getLayoutBounds()
.getWidth();
double nodesWidth = graphicWidth + padding.getLeft()
+ padding.getRight() + arrowWidth + labelWidth;
System.out.println("w: " + graphicWidth + " " + arrowWidth + " "
+ labelWidth);
graphicTextGapProperty().bind(widthProperty().subtract(nodesWidth));
try {
alert = new Image(new FileInputStream("img/Alert.png"));
registered = new Image(new FileInputStream("img/Registered.png"));
deleted = new Image(new FileInputStream("img/Deleted.png"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} }
And here's the CSS for TitledPane:
.titled-pane {
-fx-text-fill: #006FD8;
}
.titled-pane > .title {
-fx-background-color: transparent;
-fx-border-color: linear-gradient(to right, white 0%, grey 30%, grey 70%, white 100%) transparent transparent transparent;
}
.titled-pane:expanded > .title {
-fx-border-color: grey transparent transparent transparent;
-fx-background-color: linear-gradient(to bottom, #DCE7F5, white);
}
.titled-pane:expanded > *.content {
-fx-border-width: 0;
}
Based on the code shown by the OP on his edited question, this code addresses the fact that the titled pane is created on a listener before the stage is shown, on a custom class.
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new StackPane(), 300, 250);
primaryStage.setScene(scene);
primaryStage.setOnShown(e -> {
CustomTitledPane customTitledPane = new CustomTitledPane("Title", new StackPane(new Label("Graphic to the Right")));
scene.setRoot(customTitledPane);
customTitledPane.applyCss();
customTitledPane.layout();
// title region
Node titleRegion=customTitledPane.lookup(".title");
// padding
Insets padding=((StackPane)titleRegion).getPadding();
// image width
double graphicWidth=customTitledPane.getGraphic().getLayoutBounds().getWidth();
// arrow
double arrowWidth=titleRegion.lookup(".arrow-button").getLayoutBounds().getWidth();
// text
double labelWidth=titleRegion.lookup(".text").getLayoutBounds().getWidth();
double nodesWidth = graphicWidth+padding.getLeft()+padding.getRight()+arrowWidth+labelWidth;
customTitledPane.graphicTextGapProperty().bind(customTitledPane.widthProperty().subtract(nodesWidth));
});
primaryStage.show();
}
class CustomTitledPane extends TitledPane {
public CustomTitledPane(String titleText, Node node) {
super(titleText, node);
setAnimated(true);
setCollapsible(true);
ImageView img = new ImageView(new Image(getClass().getResource("unlock24.png").toExternalForm()));
img.setFitHeight(10d);
img.setPreserveRatio(true);
img.setSmooth(true);
setGraphic(img);
setContentDisplay(ContentDisplay.RIGHT);
}
}
There's no need to wrap graphic and text in a box, since you can select how to display your content with setContentDisplay():
title.setContentDisplay(ContentDisplay.RIGHT);
Once you have the image at the right you need to set the gap between the image and the text. For that, we can use some lookups to get the real dimensions of the nodes in the title, once the stage is shown.
Finally, we bind the gap space to the width property of the title subtracting those dimensions.
EDIT
The sample now supports creation before the stage is shown.
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new StackPane(), 300, 250);
primaryStage.setScene(scene);
primaryStage.setOnShown(e -> {
TitledPane title = new TitledPane("Title",
new StackPane(new Label("Graphic to the Right")));
ImageView imageView = new ImageView(new Image(getClass().getResource("unlock24.png").toExternalForm()));
title.setGraphic(imageView);
title.setContentDisplay(ContentDisplay.RIGHT);
scene.setRoot(title);
// apply css and force layout of nodes
title.applyCss();
title.layout();
// title region
Node titleRegion=title.lookup(".title");
// padding
Insets padding=((StackPane)titleRegion).getPadding();
// image width
double graphicWidth=imageView.getLayoutBounds().getWidth();
// arrow
double arrowWidth=titleRegion.lookup(".arrow-button").getLayoutBounds().getWidth();
// text
double labelWidth=titleRegion.lookup(".text").getLayoutBounds().getWidth();
double nodesWidth = graphicWidth+padding.getLeft()+padding.getRight()+arrowWidth+labelWidth;
title.graphicTextGapProperty().bind(title.widthProperty().subtract(nodesWidth));
});
primaryStage.show();
}
And this is how it looks like:
Related
How can I make a Region equal to another in JavaFX?
So I was making a UI in JavaFX and was using Regions and setting the shape to an SVG path and style to turn it onto an icon. SVGPath userIcon = new SVGPath(); userIcon.setContent("M55,27.5C55,12.337,42.663,0,27.5,0S0,12.337,0,27.5c0,8.009,3.444,15.228,8.926,20.258l-0.026,0.023l0.892,0.752c0.058,0.049,0.121,0.089,0.179,0.137c0.474,0.393,0.965,0.766,1.465,1.127c0.162,0.117,0.324,0.234,0.489,0.348c0.534,0.368,1.082,0.717,1.642,1.048c0.122,0.072,0.245,0.142,0.368,0.212c0.613,0.349,1.239,0.678,1.88,0.98c0.047,0.022,0.095,0.042,0.142,0.064c2.089,0.971,4.319,1.684,6.651,2.105c0.061,0.011,0.122,0.022,0.184,0.033c0.724,0.125,1.456,0.225,2.197,0.292c0.09,0.008,0.18,0.013,0.271,0.021C25.998,54.961,26.744,55,27.5,55c0.749,0,1.488-0.039,2.222-0.098c0.093-0.008,0.186-0.013,0.279-0.021c0.735-0.067,1.461-0.164,2.178-0.287c0.062-0.011,0.125-0.022,0.187-0.034c2.297-0.412,4.495-1.109,6.557-2.055c0.076-0.035,0.153-0.068,0.229-0.104c0.617-0.29,1.22-0.603,1.811-0.936c0.147-0.083,0.293-0.167,0.439-0.253c0.538-0.317,1.067-0.648,1.581-1c0.185-0.126,0.366-0.259,0.549-0.391c0.439-0.316,0.87-0.642,1.289-0.983c0.093-0.075,0.193-0.14,0.284-0.217l0.915-0.764l-0.027-0.023C51.523,42.802,55,35.55,55,27.5z M2,27.5C2,13.439,13.439,2,27.5,2S53,13.439,53,27.5c0,7.577-3.325,14.389-8.589,19.063c-0.294-0.203-0.59-0.385-0.893-0.537l-8.467-4.233c-0.76-0.38-1.232-1.144-1.232-1.993v-2.957c0.196-0.242,0.403-0.516,0.617-0.817c1.096-1.548,1.975-3.27,2.616-5.123c1.267-0.602,2.085-1.864,2.085-3.289v-3.545c0-0.867-0.318-1.708-0.887-2.369v-4.667c0.052-0.519,0.236-3.448-1.883-5.864C34.524,9.065,31.541,8,27.5,8s-7.024,1.065-8.867,3.168c-2.119,2.416-1.935,5.345-1.883,5.864v4.667c-0.568,0.661-0.887,1.502-0.887,2.369v3.545c0,1.101,0.494,2.128,1.34,2.821c0.81,3.173,2.477,5.575,3.093,6.389v2.894c0,0.816-0.445,1.566-1.162,1.958l-7.907,4.313c-0.252,0.137-0.502,0.297-0.752,0.476C5.276,41.792,2,35.022,2,27.5z M42.459,48.132c-0.35,0.254-0.706,0.5-1.067,0.735c-0.166,0.108-0.331,0.216-0.5,0.321c-0.472,0.292-0.952,0.57-1.442,0.83c-0.108,0.057-0.217,0.111-0.326,0.167c-1.126,0.577-2.291,1.073-3.488,1.476c-0.042,0.014-0.084,0.029-0.127,0.043c-0.627,0.208-1.262,0.393-1.904,0.552c-0.002,0-0.004,0.001-0.006,0.001c-0.648,0.16-1.304,0.293-1.964,0.402c-0.018,0.003-0.036,0.007-0.054,0.01c-0.621,0.101-1.247,0.174-1.875,0.229c-0.111,0.01-0.222,0.017-0.334,0.025C28.751,52.97,28.127,53,27.5,53c-0.634,0-1.266-0.031-1.895-0.078c-0.109-0.008-0.218-0.015-0.326-0.025c-0.634-0.056-1.265-0.131-1.89-0.233c-0.028-0.005-0.056-0.01-0.084-0.015c-1.322-0.221-2.623-0.546-3.89-0.971c-0.039-0.013-0.079-0.027-0.118-0.04c-0.629-0.214-1.251-0.451-1.862-0.713c-0.004-0.002-0.009-0.004-0.013-0.006c-0.578-0.249-1.145-0.525-1.705-0.816c-0.073-0.038-0.147-0.074-0.219-0.113c-0.511-0.273-1.011-0.568-1.504-0.876c-0.146-0.092-0.291-0.185-0.435-0.279c-0.454-0.297-0.902-0.606-1.338-0.933c-0.045-0.034-0.088-0.07-0.133-0.104c0.032-0.018,0.064-0.036,0.096-0.054l7.907-4.313c1.36-0.742,2.205-2.165,2.205-3.714l-0.001-3.602l-0.23-0.278c-0.022-0.025-2.184-2.655-3.001-6.216l-0.091-0.396l-0.341-0.221c-0.481-0.311-0.769-0.831-0.769-1.392v-3.545c0-0.465,0.197-0.898,0.557-1.223l0.33-0.298v-5.57l-0.009-0.131c-0.003-0.024-0.298-2.429,1.396-4.36C21.583,10.837,24.061,10,27.5,10c3.426,0,5.896,0.83,7.346,2.466c1.692,1.911,1.415,4.361,1.413,4.381l-0.009,5.701l0.33,0.298c0.359,0.324,0.557,0.758,0.557,1.223v3.545c0,0.713-0.485,1.36-1.181,1.575l-0.497,0.153l-0.16,0.495c-0.59,1.833-1.43,3.526-2.496,5.032c-0.262,0.37-0.517,0.698-0.736,0.949l-0.248,0.283V39.8c0,1.612,0.896,3.062,2.338,3.782l8.467,4.233c0.054,0.027,0.107,0.055,0.16,0.083C42.677,47.979,42.567,48.054,42.459,48.132z"); //BookNow Icon SVGPath bookNowIcon = new SVGPath(); bookNowIcon.setContent("m435.710938 117.226562-6.925782-4 12-20.796874 6.925782 4 12-20.800782c3.1875-5.515625 4.050781-12.074218 2.398437-18.226562-1.648437-6.152344-5.679687-11.394532-11.199219-14.574219l-13.863281-8c-5.515625-3.1875-12.070313-4.050781-18.222656-2.398437-6.152344 1.652343-11.394531 5.679687-14.578125 11.199218l-12 20.800782 6.929687 4-12 20.796874-6.929687-4-12.246094 21.28125v-106.296874h-320c-26.5.027343-47.9726562 21.503906-48 48v352c.0273438 26.5 21.5 47.972656 48 48h320v-213.703126l59.710938-103.421874 13.855468 8-24 41.597656 13.859375 8 32-55.421875zm-6.640626-68.503906 13.859376 8c1.835937 1.0625 3.179687 2.8125 3.730468 4.863282.546875 2.050781.257813 4.234374-.804687 6.074218l-4 6.929688-27.710938-16 4-6.929688c2.207031-3.828125 7.097657-5.144531 10.925781-2.9375zm-14.613281 28.519532 12.472657 7.203124-12 20.796876-13.859376-8 12-20.796876zm-366.457031-61.03125h304v24h-312v16h312v24h-304c-17.671875 0-32-14.324219-32-32 0-17.671876 14.328125-32 32-32zm304 416h-296v-296h-16v294.863281c-14.085938-3.636719-23.945312-16.316407-24-30.863281v-316.320313c6.738281 6.0625 15.0625 10.085937 24 11.601563v24.71875h16v-24h296v38.007812l-116.65625 202.058594-4.289062 71.429687 59.714843-39.429687 61.230469-106.058594zm-101.039062-89.09375 26.078124 15.054687-28.09375 18.542969zm34.894531 1.664062-6.925781-4 108-187.058594-13.859376-8-108 187.058594-3.460937-2-3.464844-2 128-221.695312 27.710938 16zm0 0"); //Records Icon SVGPath recordsIcon = new SVGPath(); recordsIcon.setContent("m72.808594 48h-64.960938c-4.332031.003906-7.84374975 3.515625-7.847656 7.847656v384.304688c.00390625 4.332031 3.515625 7.84375 7.847656 7.847656h288.3125c4.332032-.003906 7.84375-3.515625 7.847656-7.847656v-384.304688c-.003906-4.332031-3.515624-7.84375-7.847656-7.847656h-64.953125c-3.828125 18.613281-20.199219 31.976562-39.199219 32h-80c-19-.023438-35.371093-13.386719-39.199218-32zm215.199218 360h-272v-16h272zm0-32h-272v-16h272zm0-32h-272v-16h272zm0-32h-272v-16h272zm0-32h-272v-16h272zm-183.160156-175.960938c3.742188.394532 6.699219 3.34375 7.113282 7.082032l5.382812 48.4375 11.808594-19.679688c1.640625-2.726562 4.746094-4.222656 7.902344-3.804687s5.761718 2.664062 6.640624 5.726562l8.90625 31.136719 15.8125-47.464844c1.023438-3.074218 3.796876-5.230468 7.027344-5.460937 3.230469-.226563 6.28125 1.511719 7.726563 4.414062l13.785156 27.574219h91.054687v16h-96c-3.046874.015625-5.839843-1.699219-7.199218-4.425781l-7.359375-14.726563-17.890625 53.679688c-1.136719 3.304687-4.261719 5.511718-7.757813 5.472656-3.507812-.074219-6.558593-2.425781-7.519531-5.800781l-10.9375-38.269531-14.519531 24.191406c-1.769531 2.941406-5.214844 4.425781-8.566407 3.691406-3.351562-.730469-5.863281-3.523438-6.242187-6.933594l-4-35.789062-20.480469 61.4375c-1.050781 3.152344-3.9375 5.324218-7.253906 5.464844h-.273438c-3.199218 0-6.089843-1.90625-7.351562-4.847657l-21.921875-51.144531h-26.726563v-16h32c3.199219 0 6.089844 1.90625 7.351563 4.847656l15.710937 36.65625 25.34375-76c1.195313-3.5625 4.695313-5.832031 8.433594-5.464844zm0 0"); ...More like that... //Set Region Shapes profileSVGRegion.setShape(userIcon); bookNowSVGRegion.setShape(bookNowIcon); recordsSVGRegion.setShape(recordsIcon); ...More like that... The problem is that it was too recursive(had like 15 icons) and I decided to write a function to do it, Region createRegionIcon(String svgData, String color){ Region svgRegion = new Region(); SVGPath icon = new SVGPath(); icon.setContent(svgData); svgRegion.setShape(icon); svgRegion.setStyle("-fx-background-color: " + color); return svgRegion; } but it just wasn't doing what I expected. When I set the regions equal to the function, nothing would happen. addressSVGRegion = createRegionIcon("Some random SVGPath data", "#123456");
You have to set the size of the ´Region´. Try modifying your method to: private final double width = 50; private final double height = 50; private static Region createRegionIcon(String svgData, String color) { SVGPath icon = new SVGPath(); icon.setContent(svgData); Region svgRegion = new Region(); svgRegion.setShape(icon); svgRegion.setMinSize(width, height); svgRegion.setPrefSize(width, height); svgRegion.setMaxSize(width, height); svgRegion.setStyle("-fx-background-color: " + color); return svgRegion; } Working example: import javafx.application.Application; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.layout.HBox; import javafx.scene.layout.Region; import javafx.scene.shape.SVGPath; import javafx.stage.Stage; public class App extends Application { private static final double WIDTH = 50; private static final double HEIGHT = 50; private final String svgData1 = "M55,27.5C55,12.337,42.663,0,27.5,0S0,12.337,0,27.5c0,8.009,3.444,15.228,8.926,20.258l-0.026,0.023l0.892,0.752c0.058,0.049,0.121,0.089,0.179,0.137c0.474,0.393,0.965,0.766,1.465,1.127c0.162,0.117,0.324,0.234,0.489,0.348c0.534,0.368,1.082,0.717,1.642,1.048c0.122,0.072,0.245,0.142,0.368,0.212c0.613,0.349,1.239,0.678,1.88,0.98c0.047,0.022,0.095,0.042,0.142,0.064c2.089,0.971,4.319,1.684,6.651,2.105c0.061,0.011,0.122,0.022,0.184,0.033c0.724,0.125,1.456,0.225,2.197,0.292c0.09,0.008,0.18,0.013,0.271,0.021C25.998,54.961,26.744,55,27.5,55c0.749,0,1.488-0.039,2.222-0.098c0.093-0.008,0.186-0.013,0.279-0.021c0.735-0.067,1.461-0.164,2.178-0.287c0.062-0.011,0.125-0.022,0.187-0.034c2.297-0.412,4.495-1.109,6.557-2.055c0.076-0.035,0.153-0.068,0.229-0.104c0.617-0.29,1.22-0.603,1.811-0.936c0.147-0.083,0.293-0.167,0.439-0.253c0.538-0.317,1.067-0.648,1.581-1c0.185-0.126,0.366-0.259,0.549-0.391c0.439-0.316,0.87-0.642,1.289-0.983c0.093-0.075,0.193-0.14,0.284-0.217l0.915-0.764l-0.027-0.023C51.523,42.802,55,35.55,55,27.5z M2,27.5C2,13.439,13.439,2,27.5,2S53,13.439,53,27.5c0,7.577-3.325,14.389-8.589,19.063c-0.294-0.203-0.59-0.385-0.893-0.537l-8.467-4.233c-0.76-0.38-1.232-1.144-1.232-1.993v-2.957c0.196-0.242,0.403-0.516,0.617-0.817c1.096-1.548,1.975-3.27,2.616-5.123c1.267-0.602,2.085-1.864,2.085-3.289v-3.545c0-0.867-0.318-1.708-0.887-2.369v-4.667c0.052-0.519,0.236-3.448-1.883-5.864C34.524,9.065,31.541,8,27.5,8s-7.024,1.065-8.867,3.168c-2.119,2.416-1.935,5.345-1.883,5.864v4.667c-0.568,0.661-0.887,1.502-0.887,2.369v3.545c0,1.101,0.494,2.128,1.34,2.821c0.81,3.173,2.477,5.575,3.093,6.389v2.894c0,0.816-0.445,1.566-1.162,1.958l-7.907,4.313c-0.252,0.137-0.502,0.297-0.752,0.476C5.276,41.792,2,35.022,2,27.5z M42.459,48.132c-0.35,0.254-0.706,0.5-1.067,0.735c-0.166,0.108-0.331,0.216-0.5,0.321c-0.472,0.292-0.952,0.57-1.442,0.83c-0.108,0.057-0.217,0.111-0.326,0.167c-1.126,0.577-2.291,1.073-3.488,1.476c-0.042,0.014-0.084,0.029-0.127,0.043c-0.627,0.208-1.262,0.393-1.904,0.552c-0.002,0-0.004,0.001-0.006,0.001c-0.648,0.16-1.304,0.293-1.964,0.402c-0.018,0.003-0.036,0.007-0.054,0.01c-0.621,0.101-1.247,0.174-1.875,0.229c-0.111,0.01-0.222,0.017-0.334,0.025C28.751,52.97,28.127,53,27.5,53c-0.634,0-1.266-0.031-1.895-0.078c-0.109-0.008-0.218-0.015-0.326-0.025c-0.634-0.056-1.265-0.131-1.89-0.233c-0.028-0.005-0.056-0.01-0.084-0.015c-1.322-0.221-2.623-0.546-3.89-0.971c-0.039-0.013-0.079-0.027-0.118-0.04c-0.629-0.214-1.251-0.451-1.862-0.713c-0.004-0.002-0.009-0.004-0.013-0.006c-0.578-0.249-1.145-0.525-1.705-0.816c-0.073-0.038-0.147-0.074-0.219-0.113c-0.511-0.273-1.011-0.568-1.504-0.876c-0.146-0.092-0.291-0.185-0.435-0.279c-0.454-0.297-0.902-0.606-1.338-0.933c-0.045-0.034-0.088-0.07-0.133-0.104c0.032-0.018,0.064-0.036,0.096-0.054l7.907-4.313c1.36-0.742,2.205-2.165,2.205-3.714l-0.001-3.602l-0.23-0.278c-0.022-0.025-2.184-2.655-3.001-6.216l-0.091-0.396l-0.341-0.221c-0.481-0.311-0.769-0.831-0.769-1.392v-3.545c0-0.465,0.197-0.898,0.557-1.223l0.33-0.298v-5.57l-0.009-0.131c-0.003-0.024-0.298-2.429,1.396-4.36C21.583,10.837,24.061,10,27.5,10c3.426,0,5.896,0.83,7.346,2.466c1.692,1.911,1.415,4.361,1.413,4.381l-0.009,5.701l0.33,0.298c0.359,0.324,0.557,0.758,0.557,1.223v3.545c0,0.713-0.485,1.36-1.181,1.575l-0.497,0.153l-0.16,0.495c-0.59,1.833-1.43,3.526-2.496,5.032c-0.262,0.37-0.517,0.698-0.736,0.949l-0.248,0.283V39.8c0,1.612,0.896,3.062,2.338,3.782l8.467,4.233c0.054,0.027,0.107,0.055,0.16,0.083C42.677,47.979,42.567,48.054,42.459,48.132z"; private final String svgData2 = "m435.710938 117.226562-6.925782-4 12-20.796874 6.925782 4 12-20.800782c3.1875-5.515625 4.050781-12.074218 2.398437-18.226562-1.648437-6.152344-5.679687-11.394532-11.199219-14.574219l-13.863281-8c-5.515625-3.1875-12.070313-4.050781-18.222656-2.398437-6.152344 1.652343-11.394531 5.679687-14.578125 11.199218l-12 20.800782 6.929687 4-12 20.796874-6.929687-4-12.246094 21.28125v-106.296874h-320c-26.5.027343-47.9726562 21.503906-48 48v352c.0273438 26.5 21.5 47.972656 48 48h320v-213.703126l59.710938-103.421874 13.855468 8-24 41.597656 13.859375 8 32-55.421875zm-6.640626-68.503906 13.859376 8c1.835937 1.0625 3.179687 2.8125 3.730468 4.863282.546875 2.050781.257813 4.234374-.804687 6.074218l-4 6.929688-27.710938-16 4-6.929688c2.207031-3.828125 7.097657-5.144531 10.925781-2.9375zm-14.613281 28.519532 12.472657 7.203124-12 20.796876-13.859376-8 12-20.796876zm-366.457031-61.03125h304v24h-312v16h312v24h-304c-17.671875 0-32-14.324219-32-32 0-17.671876 14.328125-32 32-32zm304 416h-296v-296h-16v294.863281c-14.085938-3.636719-23.945312-16.316407-24-30.863281v-316.320313c6.738281 6.0625 15.0625 10.085937 24 11.601563v24.71875h16v-24h296v38.007812l-116.65625 202.058594-4.289062 71.429687 59.714843-39.429687 61.230469-106.058594zm-101.039062-89.09375 26.078124 15.054687-28.09375 18.542969zm34.894531 1.664062-6.925781-4 108-187.058594-13.859376-8-108 187.058594-3.460937-2-3.464844-2 128-221.695312 27.710938 16zm0 0"; private final String svgData3 = "m72.808594 48h-64.960938c-4.332031.003906-7.84374975 3.515625-7.847656 7.847656v384.304688c.00390625 4.332031 3.515625 7.84375 7.847656 7.847656h288.3125c4.332032-.003906 7.84375-3.515625 7.847656-7.847656v-384.304688c-.003906-4.332031-3.515624-7.84375-7.847656-7.847656h-64.953125c-3.828125 18.613281-20.199219 31.976562-39.199219 32h-80c-19-.023438-35.371093-13.386719-39.199218-32zm215.199218 360h-272v-16h272zm0-32h-272v-16h272zm0-32h-272v-16h272zm0-32h-272v-16h272zm0-32h-272v-16h272zm-183.160156-175.960938c3.742188.394532 6.699219 3.34375 7.113282 7.082032l5.382812 48.4375 11.808594-19.679688c1.640625-2.726562 4.746094-4.222656 7.902344-3.804687s5.761718 2.664062 6.640624 5.726562l8.90625 31.136719 15.8125-47.464844c1.023438-3.074218 3.796876-5.230468 7.027344-5.460937 3.230469-.226563 6.28125 1.511719 7.726563 4.414062l13.785156 27.574219h91.054687v16h-96c-3.046874.015625-5.839843-1.699219-7.199218-4.425781l-7.359375-14.726563-17.890625 53.679688c-1.136719 3.304687-4.261719 5.511718-7.757813 5.472656-3.507812-.074219-6.558593-2.425781-7.519531-5.800781l-10.9375-38.269531-14.519531 24.191406c-1.769531 2.941406-5.214844 4.425781-8.566407 3.691406-3.351562-.730469-5.863281-3.523438-6.242187-6.933594l-4-35.789062-20.480469 61.4375c-1.050781 3.152344-3.9375 5.324218-7.253906 5.464844h-.273438c-3.199218 0-6.089843-1.90625-7.351562-4.847657l-21.921875-51.144531h-26.726563v-16h32c3.199219 0 6.089844 1.90625 7.351563 4.847656l15.710937 36.65625 25.34375-76c1.195313-3.5625 4.695313-5.832031 8.433594-5.464844zm0 0"; #Override public void start(Stage stage) { Region svgShape1 = createRegionIcon(svgData1, "blue"); Region svgShape2 = createRegionIcon(svgData2, "red"); Region svgShape3 = createRegionIcon(svgData3, "green"); HBox pane = new HBox(); pane.setAlignment(Pos.CENTER); pane.setSpacing(10); pane.setStyle("-fx-background-color: white;"); pane.getChildren().addAll(svgShape1, svgShape2, svgShape3); Scene scene = new Scene(pane); stage.setScene(scene); stage.show(); } private static Region createRegionIcon(String svgData, String color) { SVGPath icon = new SVGPath(); icon.setContent(svgData); Region svgRegion = new Region(); svgRegion.setShape(icon); svgRegion.setMinSize(WIDTH, HEIGHT); svgRegion.setPrefSize(WIDTH, HEIGHT); svgRegion.setMaxSize(WIDTH, HEIGHT); svgRegion.setStyle("-fx-background-color: " + color); return svgRegion; } public static void main(String[] args) { launch(); } } Output:
Regions can be shaped in CSS using the -fx-shape CSS property Using this technique, the explicit creation of an SVGPath is not necessary. See moderna.css in the JavaFX source for many examples of applying shapes to regions. If you wanted two regions to have the same shape, you could do that by applying the same style class to different instances of Region. The shaped regions can be colored by setting the -fx-background-color. The shaped regions won't be seen unless they have a non-zero size. The region size can be managed via min/max/pref height/width settings (either in java code, FXML, or CSS). These settings provide instructions to the layout pane enclosing the region on how to size that region. Here is an example of using -fx-shape to shape regions. The code is based on that in Oboe's answer, just adapted to use an external style sheet and slightly different coloring. region-styling.css .layout-pane { -fx-spacing: 10; -fx-background-color: white; } .icon { -fx-min-width: 50; -fx-pref-width: 50; -fx-max-width: 50; -fx-min-height: 50; -fx-pref-height: 50; -fx-max-height: 50; } .user-icon { -fx-shape: "M55,27.5C55,12.337,42.663,0,27.5,0S0,12.337,0,27.5c0,8.009,3.444,15.228,8.926,20.258l-0.026,0.023l0.892,0.752c0.058,0.049,0.121,0.089,0.179,0.137c0.474,0.393,0.965,0.766,1.465,1.127c0.162,0.117,0.324,0.234,0.489,0.348c0.534,0.368,1.082,0.717,1.642,1.048c0.122,0.072,0.245,0.142,0.368,0.212c0.613,0.349,1.239,0.678,1.88,0.98c0.047,0.022,0.095,0.042,0.142,0.064c2.089,0.971,4.319,1.684,6.651,2.105c0.061,0.011,0.122,0.022,0.184,0.033c0.724,0.125,1.456,0.225,2.197,0.292c0.09,0.008,0.18,0.013,0.271,0.021C25.998,54.961,26.744,55,27.5,55c0.749,0,1.488-0.039,2.222-0.098c0.093-0.008,0.186-0.013,0.279-0.021c0.735-0.067,1.461-0.164,2.178-0.287c0.062-0.011,0.125-0.022,0.187-0.034c2.297-0.412,4.495-1.109,6.557-2.055c0.076-0.035,0.153-0.068,0.229-0.104c0.617-0.29,1.22-0.603,1.811-0.936c0.147-0.083,0.293-0.167,0.439-0.253c0.538-0.317,1.067-0.648,1.581-1c0.185-0.126,0.366-0.259,0.549-0.391c0.439-0.316,0.87-0.642,1.289-0.983c0.093-0.075,0.193-0.14,0.284-0.217l0.915-0.764l-0.027-0.023C51.523,42.802,55,35.55,55,27.5z M2,27.5C2,13.439,13.439,2,27.5,2S53,13.439,53,27.5c0,7.577-3.325,14.389-8.589,19.063c-0.294-0.203-0.59-0.385-0.893-0.537l-8.467-4.233c-0.76-0.38-1.232-1.144-1.232-1.993v-2.957c0.196-0.242,0.403-0.516,0.617-0.817c1.096-1.548,1.975-3.27,2.616-5.123c1.267-0.602,2.085-1.864,2.085-3.289v-3.545c0-0.867-0.318-1.708-0.887-2.369v-4.667c0.052-0.519,0.236-3.448-1.883-5.864C34.524,9.065,31.541,8,27.5,8s-7.024,1.065-8.867,3.168c-2.119,2.416-1.935,5.345-1.883,5.864v4.667c-0.568,0.661-0.887,1.502-0.887,2.369v3.545c0,1.101,0.494,2.128,1.34,2.821c0.81,3.173,2.477,5.575,3.093,6.389v2.894c0,0.816-0.445,1.566-1.162,1.958l-7.907,4.313c-0.252,0.137-0.502,0.297-0.752,0.476C5.276,41.792,2,35.022,2,27.5z M42.459,48.132c-0.35,0.254-0.706,0.5-1.067,0.735c-0.166,0.108-0.331,0.216-0.5,0.321c-0.472,0.292-0.952,0.57-1.442,0.83c-0.108,0.057-0.217,0.111-0.326,0.167c-1.126,0.577-2.291,1.073-3.488,1.476c-0.042,0.014-0.084,0.029-0.127,0.043c-0.627,0.208-1.262,0.393-1.904,0.552c-0.002,0-0.004,0.001-0.006,0.001c-0.648,0.16-1.304,0.293-1.964,0.402c-0.018,0.003-0.036,0.007-0.054,0.01c-0.621,0.101-1.247,0.174-1.875,0.229c-0.111,0.01-0.222,0.017-0.334,0.025C28.751,52.97,28.127,53,27.5,53c-0.634,0-1.266-0.031-1.895-0.078c-0.109-0.008-0.218-0.015-0.326-0.025c-0.634-0.056-1.265-0.131-1.89-0.233c-0.028-0.005-0.056-0.01-0.084-0.015c-1.322-0.221-2.623-0.546-3.89-0.971c-0.039-0.013-0.079-0.027-0.118-0.04c-0.629-0.214-1.251-0.451-1.862-0.713c-0.004-0.002-0.009-0.004-0.013-0.006c-0.578-0.249-1.145-0.525-1.705-0.816c-0.073-0.038-0.147-0.074-0.219-0.113c-0.511-0.273-1.011-0.568-1.504-0.876c-0.146-0.092-0.291-0.185-0.435-0.279c-0.454-0.297-0.902-0.606-1.338-0.933c-0.045-0.034-0.088-0.07-0.133-0.104c0.032-0.018,0.064-0.036,0.096-0.054l7.907-4.313c1.36-0.742,2.205-2.165,2.205-3.714l-0.001-3.602l-0.23-0.278c-0.022-0.025-2.184-2.655-3.001-6.216l-0.091-0.396l-0.341-0.221c-0.481-0.311-0.769-0.831-0.769-1.392v-3.545c0-0.465,0.197-0.898,0.557-1.223l0.33-0.298v-5.57l-0.009-0.131c-0.003-0.024-0.298-2.429,1.396-4.36C21.583,10.837,24.061,10,27.5,10c3.426,0,5.896,0.83,7.346,2.466c1.692,1.911,1.415,4.361,1.413,4.381l-0.009,5.701l0.33,0.298c0.359,0.324,0.557,0.758,0.557,1.223v3.545c0,0.713-0.485,1.36-1.181,1.575l-0.497,0.153l-0.16,0.495c-0.59,1.833-1.43,3.526-2.496,5.032c-0.262,0.37-0.517,0.698-0.736,0.949l-0.248,0.283V39.8c0,1.612,0.896,3.062,2.338,3.782l8.467,4.233c0.054,0.027,0.107,0.055,0.16,0.083C42.677,47.979,42.567,48.054,42.459,48.132z"; -fx-background-color: blue; } .notepad-icon { -fx-shape: "m435.710938 117.226562-6.925782-4 12-20.796874 6.925782 4 12-20.800782c3.1875-5.515625 4.050781-12.074218 2.398437-18.226562-1.648437-6.152344-5.679687-11.394532-11.199219-14.574219l-13.863281-8c-5.515625-3.1875-12.070313-4.050781-18.222656-2.398437-6.152344 1.652343-11.394531 5.679687-14.578125 11.199218l-12 20.800782 6.929687 4-12 20.796874-6.929687-4-12.246094 21.28125v-106.296874h-320c-26.5.027343-47.9726562 21.503906-48 48v352c.0273438 26.5 21.5 47.972656 48 48h320v-213.703126l59.710938-103.421874 13.855468 8-24 41.597656 13.859375 8 32-55.421875zm-6.640626-68.503906 13.859376 8c1.835937 1.0625 3.179687 2.8125 3.730468 4.863282.546875 2.050781.257813 4.234374-.804687 6.074218l-4 6.929688-27.710938-16 4-6.929688c2.207031-3.828125 7.097657-5.144531 10.925781-2.9375zm-14.613281 28.519532 12.472657 7.203124-12 20.796876-13.859376-8 12-20.796876zm-366.457031-61.03125h304v24h-312v16h312v24h-304c-17.671875 0-32-14.324219-32-32 0-17.671876 14.328125-32 32-32zm304 416h-296v-296h-16v294.863281c-14.085938-3.636719-23.945312-16.316407-24-30.863281v-316.320313c6.738281 6.0625 15.0625 10.085937 24 11.601563v24.71875h16v-24h296v38.007812l-116.65625 202.058594-4.289062 71.429687 59.714843-39.429687 61.230469-106.058594zm-101.039062-89.09375 26.078124 15.054687-28.09375 18.542969zm34.894531 1.664062-6.925781-4 108-187.058594-13.859376-8-108 187.058594-3.460937-2-3.464844-2 128-221.695312 27.710938 16zm0 0"; -fx-background-color: green; } .cardiac-arrest-icon { -fx-shape: "m72.808594 48h-64.960938c-4.332031.003906-7.84374975 3.515625-7.847656 7.847656v384.304688c.00390625 4.332031 3.515625 7.84375 7.847656 7.847656h288.3125c4.332032-.003906 7.84375-3.515625 7.847656-7.847656v-384.304688c-.003906-4.332031-3.515624-7.84375-7.847656-7.847656h-64.953125c-3.828125 18.613281-20.199219 31.976562-39.199219 32h-80c-19-.023438-35.371093-13.386719-39.199218-32zm215.199218 360h-272v-16h272zm0-32h-272v-16h272zm0-32h-272v-16h272zm0-32h-272v-16h272zm0-32h-272v-16h272zm-183.160156-175.960938c3.742188.394532 6.699219 3.34375 7.113282 7.082032l5.382812 48.4375 11.808594-19.679688c1.640625-2.726562 4.746094-4.222656 7.902344-3.804687s5.761718 2.664062 6.640624 5.726562l8.90625 31.136719 15.8125-47.464844c1.023438-3.074218 3.796876-5.230468 7.027344-5.460937 3.230469-.226563 6.28125 1.511719 7.726563 4.414062l13.785156 27.574219h91.054687v16h-96c-3.046874.015625-5.839843-1.699219-7.199218-4.425781l-7.359375-14.726563-17.890625 53.679688c-1.136719 3.304687-4.261719 5.511718-7.757813 5.472656-3.507812-.074219-6.558593-2.425781-7.519531-5.800781l-10.9375-38.269531-14.519531 24.191406c-1.769531 2.941406-5.214844 4.425781-8.566407 3.691406-3.351562-.730469-5.863281-3.523438-6.242187-6.933594l-4-35.789062-20.480469 61.4375c-1.050781 3.152344-3.9375 5.324218-7.253906 5.464844h-.273438c-3.199218 0-6.089843-1.90625-7.351562-4.847657l-21.921875-51.144531h-26.726563v-16h32c3.199219 0 6.089844 1.90625 7.351563 4.847656l15.710937 36.65625 25.34375-76c1.195313-3.5625 4.695313-5.832031 8.433594-5.464844zm0 0"; -fx-background-color: red; } I set some items like height and width in the CSS. If using FXML for layout, you may prefer to set the layout info like height and width there. If you do so, you could set the min and max values for the width and height all to -Infinity. This value is a convention in JavaFX for a sentinel value that uses the preferred width for other values. Such a setting is not possible with CSS, so, here I just set those values explicitly to the preferred size values. RegionStyling.java import javafx.application.Application; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.layout.HBox; import javafx.scene.layout.Region; import javafx.stage.Stage; public class RegionStyling extends Application { #Override public void start(Stage stage) { HBox layout = new HBox(); layout.setAlignment(Pos.CENTER); layout.getStyleClass().add("layout-pane"); layout.getChildren().addAll( createIcon("user-icon"), createIcon("notepad-icon"), createIcon("cardiac-arrest-icon") ); Scene scene = new Scene(layout); scene.getStylesheets().add( RegionStyling.class.getResource( "region-styling.css" ).toExternalForm() ); stage.setScene(scene); stage.show(); } private static Region createIcon(String styleClass) { Region icon = new Region(); icon.getStyleClass().addAll("icon", styleClass); return icon; } public static void main(String[] args) { launch(); } }
Can't drop a rectangle at the desired location with JavaFX
I am trying to implement a full press-drag-release gesture with JavaFX. I want to drag a rectangle from one VBox to another. On the MOUSE_DRAG_RELEASED event that happens on the target VBox, I'm trying to add the dragged rectangle as a child of the target VBox. The problem is that when I release the mouse on the target VBox, the rectangle does not get into the expected position inside the VBox, but is always offset to the right by a fixed distance. public class DragFromOneVBoxToAnother extends Application { private Disk sourceDisk = new Disk(); private VBox targetVBox = new VBox(); public static void main(String[] args) { Application.launch(args); } #Override public void start(Stage stage) { // Build the UI GridPane root = getUI(); // Add the event handlers this.addEventHandlers(); Scene scene = new Scene(root, 800, 600); stage.setScene(scene); stage.show(); } private GridPane getUI() { GridPane pane = new GridPane(); VBox sourceVBox = new VBox(); sourceDisk.setWidth(90); sourceDisk.setHeight(20); sourceVBox.setStyle(" -fx-border-color:red; -fx-border-width: 1; -fx-border-style: solid;"); targetVBox.setStyle(" -fx-border-color:green; -fx-border-width: 1; -fx-border-style: solid;"); sourceVBox.getChildren().add(sourceDisk); targetVBox.getChildren().add(new Rectangle(200, 20)); pane.setHgap(200); pane.addColumn(0, sourceVBox); pane.addColumn(1, targetVBox); pane.setPadding(new Insets(200, 100, 200, 100)); return pane; } private void addEventHandlers() { sourceDisk.setOnMouseEntered(event -> sourceDisk.setCursor(Cursor.HAND)); sourceDisk.setOnMousePressed(event -> { sourceDisk.setOrgSceneX(event.getSceneX()); sourceDisk.setOrgSceneY(event.getSceneY()); sourceDisk.setOrgTranslateX(sourceDisk.getTranslateX()); sourceDisk.setOrgTranslateY(sourceDisk.getTranslateY()); sourceDisk.setMouseTransparent(true); sourceDisk.setCursor(Cursor.CLOSED_HAND); }); sourceDisk.setOnDragDetected(event -> sourceDisk.startFullDrag()); sourceDisk.setOnMouseDragged(event -> { double offsetX = event.getSceneX() - sourceDisk.getOrgSceneX(); double offsetY = event.getSceneY() - sourceDisk.getOrgSceneY(); double newTranslateX = sourceDisk.getOrgTranslateX() + offsetX; double newTranslateY = sourceDisk.getOrgTranslateY() + offsetY; sourceDisk.setTranslateX(newTranslateX); sourceDisk.setTranslateY(newTranslateY); }); sourceDisk.setOnMouseReleased(event -> { sourceDisk.setMouseTransparent(false); sourceDisk.setCursor(Cursor.DEFAULT); }); targetVBox.setOnMouseDragReleased(event -> targetVBox.getChildren().add(sourceDisk)); } private class Disk extends Rectangle { private double orgSceneX; private double orgSceneY; private double orgTranslateX; private double orgTranslateY; // below, the getters and setters for all the instance variables // were removed for brevity } I have found that, even though the visual representation of the dragged rectangle seems to be offset when it's dropped, a child appears to actually be added to the target VBox (this can be seen because the border of the VBox expands after the MOUSE_DRAG_RELEASED event). What could be the issue?
During the mouse drag gesture you modify the translateX/translateY properties of the node. This results in the dragged node being offset from the position where the new parent places it by this transformation. You need to reset those values to properly add the node to the bottom of the VBox: targetVBox.setOnMouseDragReleased(event -> { targetVBox.getChildren().add(sourceDisk); // reset translate values sourceDisk.setTranslateX(0); sourceDisk.setTranslateY(0); });
How can I build map with region selection?
I trying to build map which consist of regions(states) and when mouse entered to some region, I need handle it. Have many png images which represent each region separately. I blend my images and got what I want, but I can't handle some region. For instance: It's a first region img This is a second region img As result I got: Code: #Override public void start(Stage primaryStage) throws Exception { FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("view/MapView.fxml")); Pane root = loader.load(); primaryStage.setTitle("Map"); primaryStage.setScene(new Scene(root, 700, 700)); primaryStage.show(); //First region File file = new File("src/res/img/region1.png"); Canvas canvas = new Canvas(700, 700); canvas.addEventHandler(MouseEvent.MOUSE_ENTERED_TARGET, event -> System.out.println("Region 1")); GraphicsContext graphicsContext = canvas.getGraphicsContext2D(); graphicsContext.drawImage(new Image(file.toURI().toString()), 0, 0); root.getChildren().add(canvas); //Second region file = new File("src/res/img/region2.png"); canvas = new Canvas(700, 700); canvas.addEventHandler(MouseEvent.MOUSE_ENTERED_TARGET, event -> System.out.println("Region 2")); graphicsContext = canvas.getGraphicsContext2D(); graphicsContext.drawImage(new Image(file.toURI().toString()), 0, 0); root.getChildren().add(canvas); } In console I got always "Region 2". Please give me tips for research. Thanks in advance!
You can use an ImageView and setPickOnBounds for that. Example code: import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class LayersWithMouseEvents extends Application { #Override public void start(Stage primaryStage) { // root StackPane root = new StackPane(); // create layers Pane region1Layer = new Pane(); Pane region2Layer = new Pane(); // add layers root.getChildren().addAll(region1Layer, region2Layer); // load images ImageView region1ImageView = new ImageView( new Image( getClass().getResource("region1.png").toExternalForm())); ImageView region2ImageView = new ImageView( new Image( getClass().getResource("region2.png").toExternalForm())); // add images region1Layer.getChildren().add(region1ImageView); region2Layer.getChildren().add(region2ImageView); // mouse handler region1Layer.setOnMousePressed(e -> System.out.println("Region 1: " + e)); region2Layer.setOnMousePressed(e -> System.out.println("Region 2: " + e)); // this is the magic that allows you to click on the separate layers, but ONLY(!) as long as the layer is transparent region1Layer.setPickOnBounds(false); region2Layer.setPickOnBounds(false); primaryStage.setScene(new Scene(root, 800, 600)); primaryStage.show(); } public static void main(String[] args) { launch(args); } } In the future please create an MCVE with focus on complete. Nobody wants to waste their time in order to make your incomplete example work.
To my opinion using a canvas here is not the right approach. If you would define your regions as polygons and add them to the scene graph you can attach a listener to each of these polygons and then react accordingly if the mouse is over some region. Maybe this is also possible with image views but I have never tried wether a transparent region of an image is also mouse transparent which seems to be necessary in that case. For a program of mine I used polygons and it works nicely.
The image data can be used to determine the color of the pixels under the mouse cursor. If the pixel is not fully transparent, then the cursor is on that region. To retrieve this information you need to use a listener for the mouse moved event. For simplicity you can use a property with a listener attached to trigger the region enter/leave events: The following example assumes you keep references to the images used for the regions named image1 and image2: PixelReader reader1 = image1.getPixelReader(); PixelReader reader2 = image2.getPixelReader(); SimpleIntegerProperty region = new SimpleIntegerProperty(-1); region.addListener((observable, oldValue, newValue) -> { if (newValue.intValue() < 0) { System.out.println("region left"); } else { System.out.println("Region " + (newValue.intValue() + 1)); } }); canvas.setOnMouseMoved(event -> { int x = (int) event.getX(); int y = (int) event.getY(); if (x < image1.getWidth() && y < image1.getHeight() && reader1.getColor(x, y).getOpacity() != 0) { region.set(0); } else if (x < image2.getWidth() && y < image2.getHeight() && reader2.getColor(x, y).getOpacity() != 0) { region.set(1); } else { region.set(-1); } }); Also there is no need to create multiple Canvas to paint the images.
JavaFX scrollpane - horizontal panning with scroll wheel
I can trivially create a scroll pane in JavaFX that only scrolls horizontally like so: ScrollPane scroll = new ScrollPane(lcp); scroll.setPannable(true); scroll.setFitToHeight(true); scroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); However, the mouse scroll wheel still tries to scroll vertically rather than horizontally in this case (unless I specifically scroll over the horizontal scroll bar.) How can I set up the scroll pane so that the mouse wheel pans horizontally?
Here is the example application that I wrote for you and does exactly what you want: public class Test extends Application { ScrollPane scrollPane; int pos = 0; final int minPos = 0; final int maxPos = 100; #Override public void start(Stage primaryStage) { Label label = new Label("TEXT!!!!!!!TEXT!!!!!!!TEXT!!!!!!!TEXT!!!!!!!TEXT!!!!!!!TEXT"); label.setPrefSize(500, 100); label.setOnScroll(new EventHandler<ScrollEvent>() { #Override public void handle(ScrollEvent event) { if (event.getDeltaY() > 0) scrollPane.setHvalue(pos == minPos ? minPos : pos--); else scrollPane.setHvalue(pos == maxPos ? maxPos : pos++); } }); scrollPane = new ScrollPane(); scrollPane.setHmin(minPos); scrollPane.setHmax(maxPos); scrollPane.setVbarPolicy(ScrollBarPolicy.NEVER); scrollPane.setHbarPolicy(ScrollBarPolicy.ALWAYS); scrollPane.setPannable(true); scrollPane.setFitToHeight(true); scrollPane.setContent(label); BorderPane root = new BorderPane(); root.setPrefSize(200, 100); root.setCenter(scrollPane); primaryStage.setScene(new Scene(root)); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
I have also been looking for a solution and found this one from Ugurcan Yildirim but didn't like the fact that the natural scroll bar length and speed is modified also. This one worked for me: scrollPane.setOnScroll(event -> { if(event.getDeltaX() == 0 && event.getDeltaY() != 0) { scrollPane.setHvalue(scrollPane.getHvalue() - event.getDeltaY() / this.allComments.getWidth()); } }); event.getDeltaX() == 0 just to be sure that the user is only using the mouse wheel and nothing is adding up this.allComments is the content of the scrollPane (a HBox in my case). By dividing the delta y value by it's content width the scroll speed is natural according to the amount of content to scroll.
How to apply a blur only to a rectangular area within a pane?
Let's say I've got a StackPane which has a BackgroundImage as background and another StackPane (or another component, if neccessary) as a child. The child covers only a part of the parent StackPane. I'd like to know how to apply a GaussianBlur just to the area the child covers, so that the BackgroundImageis blurry in this area. The size of the child changes when the parent is resized. It would be perfect to get a solution that will resize just in time, too.
If you want to do it manually, you can use the snapshot function to create a snapshot image, blur it and apply it to the child every time the parent is resized. However, invoking snapshot all the time will cause performance loss. I rather suggest you create 2 images, one normal and one blurred, and display a viewport of the blurred one. Here's a more "complex" example with a circle where the viewport isn't sufficient. The clip method is used in this case: public class Lens extends Application { Image image = new Image( "http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/800px-Siberischer_tiger_de_edit02.jpg"); CirclePane circlePane; #Override public void start(Stage primaryStage) { ImageView normalImageView = new ImageView( image); ImageView blurredImageView = new ImageView( image); blurredImageView.setEffect(new GaussianBlur( 40)); Group root = new Group(); root.getChildren().addAll( normalImageView); Scene scene = new Scene( root, 1024, 768); primaryStage.setScene( scene); primaryStage.show(); // pane with clipped area circlePane = new CirclePane( blurredImageView); makeDraggable( circlePane); root.getChildren().addAll( circlePane); } public static void main(String[] args) { launch(args); } private class CirclePane extends Pane { ImageView blurredImageView; ImageView clippedView = new ImageView(); public CirclePane( ImageView blurredImageView) { this.blurredImageView = blurredImageView; // new imageview update(); getChildren().addAll( clippedView); } public void update() { // create circle Circle circle = new Circle( 200); circle.relocate( getLayoutX(), getLayoutY()); // clip image by circle blurredImageView.setClip(circle); // non-clip area should be transparent SnapshotParameters parameters = new SnapshotParameters(); parameters.setFill(Color.TRANSPARENT); // new image from clipped image WritableImage wim = null; wim = blurredImageView.snapshot(parameters, wim); clippedView.setImage( wim); } } // make node draggable class DragContext { double x; double y; } public void makeDraggable( Node node) { final DragContext dragDelta = new DragContext(); node.setOnMousePressed(mouseEvent -> { dragDelta.x = node.getBoundsInParent().getMinX() - mouseEvent.getScreenX(); dragDelta.y = node.getBoundsInParent().getMinY() - mouseEvent.getScreenY(); }); node.setOnMouseDragged(mouseEvent -> { node.relocate( mouseEvent.getScreenX() + dragDelta.x, mouseEvent.getScreenY() + dragDelta.y); circlePane.update(); }); } } Just click on the circle and drag it around.