JavaFx8 VBox center image - java

I have a JavaFx VBox inside of a ScrollPane:
VBox container = new VBox();
container.setAlignment(Pos.CENTER);
...
scrollPane.setContent(container);
scrollPane.setFitToWidth(true);
scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollBarPolicy.NEVER);
scrollPane.setMinWidth(150);
scrollPane.setPannable(true);
the size of this VBox never change, inside i have some labels, one label has an user image
like the next image(A)
the image is resized to some Height, but i don't know the size of this image, so if the width of the image is bigger than width of the VBox, this happen(part of the image hidden)(B)
but i don't want this, i want something like the following image:(the sides of the image hidden if the image width is bigger than the VBox width)(C)
http://i.stack.imgur.com/B3DOK.png
How i can do this?
I tried to put a rectangle as clip, in this rectangle i wanna show the center of the image, but the same happens.
imageView.setClip(new Rectangle(centerX - recSize, centerY - recSize, recSize*2, recSize*2));
---------------with the clip----------------
red = original image
blue = part of the image that is visible
http://i.stack.imgur.com/mYbyF.png
Nice(D)
Not nice:(E)(labels not centered correctly because of the image.)
Sorry by the links, i can't put the images directly

Solution
Set a viewport on the image not a clip.
imageView.setViewport(
new Rectangle2D(500, 320, 420, 300)
);
Sample
Here is a sample. It's not going to exactly match what you are asking for because even with the linked images in your question, I can't quite understand what you are trying to do. But I think it should give you enough background info that you can learn to accomplish what you want.
The sample creates an image view as a graphic in a scroll pane. The image view applies a viewport to the image and scales the viewport with preserved ratio. This allows a scaled portion of the much larger image to be displayed. It's kind of like a thumbnail clip (click on the thumbnail to display the full image).
import javafx.application.Application;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.*;
import javafx.stage.*;
// display a captioned image in a viewport.
// click the image to get an expanded view.
public class LabelWithImage extends Application {
private static final double IMAGE_WIDTH = 150;
#Override
public void start(Stage stage) {
Image image = new Image(IMAGE_LOC);
ImageView imageView = new ImageView(
image
);
imageView.setViewport(
new Rectangle2D(500, 320, 420, 300)
);
imageView.setFitWidth(IMAGE_WIDTH);
imageView.setPreserveRatio(true);
Label labeledImage = createCaptionedImage(
imageView,
"Village Home"
);
addGlowOnMouseOver(labeledImage);
labeledImage.setOnMouseClicked(event -> {
displayFullImage(stage, image);
});
VBox vbox = new VBox( // vbox just there to mimic question askers structure.
labeledImage
);
vbox.setPadding(new Insets(10));
ScrollPane scrollPane = makeScrollable(vbox);
Scene scene = new Scene(
scrollPane
);
stage.setScene(scene);
stage.show();
stage.setMaxWidth(stage.getWidth());
stage.setMaxHeight(stage.getHeight());
}
private void displayFullImage(Stage stage, Image image) {
Stage displayStage = new Stage();
displayStage.initStyle(StageStyle.UTILITY);
displayStage.initModality(Modality.APPLICATION_MODAL);
displayStage.initOwner(stage);
displayStage.setScene(
new Scene(
new Group(
new ImageView(
image
)
)
)
);
displayStage.show();
}
private void addGlowOnMouseOver(Node node) {
Glow glow = new Glow();
DropShadow shadow = new DropShadow(20, Color.GOLD);
glow.setInput(shadow);
node.setOnMousePressed(event -> node.setEffect(null));
node.setOnMouseEntered(event -> node.setEffect(glow));
node.setOnMouseExited(event -> node.setEffect(null));
}
private ScrollPane makeScrollable(Node node) {
ScrollPane scrollPane = new ScrollPane(node);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrollPane.setPannable(true);
return scrollPane;
}
private Label createCaptionedImage(ImageView imageView, String caption) {
Label labeledImage = new Label(caption);
labeledImage.setFont(Font.font("Athelas", FontPosture.ITALIC, 20));
labeledImage.setStyle("-fx-background-color: cornsilk");
labeledImage.setPadding(new Insets(0, 0, 5, 0));
labeledImage.setGraphic(
imageView
);
labeledImage.setContentDisplay(ContentDisplay.TOP);
return labeledImage;
}
public static void main(String[] args) {
launch(args);
}
private static final String IMAGE_LOC =
"http://www.imgion.com/images/01/beautiful-village-home.jpg";
// image courtesy of http://www.imgion.com which provides
// "free images on large topics to share with your friends and on your blogs."
}

Related

JavaFX BorderPane Layout (Stretch Left and Right Pane)

I am using a BorderPane to implement a layout in JavaFX.
Suppose the BorderPane's maxPrefWidth is set to 1000. There is a button in the left pane, and a button in the right pane. In the center pane, there is another button with an unknown size.
If: the middle element's width is 500, then the left and right nodes
should be 250 in width.
If: the middle element's width is 600, then the left and right nodes
should be 200 in width.
Is there a way to tell the left and right pane to automatically grow (horizontally) until the center node's is hit?
BorderPane expands middle area, by design
Your intentions do not mesh with the design intentions of BorderPane.
To quote the Javadoc:
The top and bottom children will be resized to their preferred heights and extend the width of the border pane. The left and right children will be resized to their preferred widths and extend the length between the top and bottom nodes. And the center node will be resized to fill the available space in the middle. Any of the positions may be null.
This means:
The center expands to take all extra space.
The top and bottom take maximum width and their preferred height.
The left and right areas take their preferred width and maximum height.
Imagine the middle as a box with a strongman inside pushing up, down, and out.
This logic is often quite handy for many business apps. The outside areas are often used for navigation, breadcrumbs, menu bar, tool bar, status bar, and so on. The inner area then holds the main content of interest. Given such usage, it makes sense to allocate only necessary space to the outer areas, and allocate most space to the inner content area.
For example, here is an entire example app using JavaFX 14.
In the center area of this example app, we place an HBox layout containing a single button. We set the background color of that layout to cornflowerblue color to make visible how the content of the center area expands to take all extra space.
package work.basil.example;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import java.time.ZonedDateTime;
/**
* JavaFX App
*/
public class App extends Application
{
#Override
public void start ( Stage stage )
{
// Widgets
ToolBar toolBar = new ToolBar();
Button button = new Button( "Click Me" );
toolBar.getItems().add( button );
Button buttonLeft = new Button( "Left" );
Button buttonRight = new Button( "Right" );
HBox appContent = new HBox( new Button( "Bonjour le monde" ) );
appContent.setStyle( "-fx-background-color: cornflowerblue;" );
HBox statusBar = new HBox( new Label( "Status goes here. Now: " + ZonedDateTime.now() ) );
// Arrange
BorderPane borderPane = new BorderPane();
borderPane.setTop( toolBar );
borderPane.setLeft( buttonLeft );
borderPane.setCenter( appContent );
borderPane.setRight( buttonRight );
borderPane.setBottom( statusBar );
var scene = new Scene( borderPane , 1000 , 1000 );
stage.setScene( scene );
stage.show();
}
public static void main ( String[] args )
{
launch();
}
}
Choose another layout
As commented on the Question, you should be using a different layout manager given your intentions.
You might be able to get by with a HBox. For maximum control, you will need to invest some time into mastering the GridPane.
GridPane
Your Question is not completely clear. If what you want is for the center content to be fixed width of 500 pixels while the left and right are flexible, being allocated any extra space proportionally, then use GridPane while setting the ColumnConstraints to Priority.SOMETIMES or Priority.ALWAYS on the left and right cells.
Here is a complete example app.
We put one button, each nested in a colored HBox, in each cell of the single-row GridPane. The colors dramatize the sizing behavior being shown here. Alternatively, you could drop the colored HBox, instead calling gridPane.setStyle( "-fx-grid-lines-visible: true ;" ) to show border lines around each cell.
package work.basil.example;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.time.ZonedDateTime;
/**
* JavaFX App
*/
public class App extends Application
{
#Override
public void start ( Stage stage )
{
// Widgets
Button buttonLeft = new Button( "Left" );
HBox left = new HBox( buttonLeft );
left.setStyle( "-fx-background-color: Salmon;" );
Button buttonCenter = new Button( "Center" );
HBox center = new HBox( buttonCenter );
center.setStyle( "-fx-background-color: CornflowerBlue;" );
Button buttonRight = new Button( "Right" );
HBox right = new HBox( buttonRight );
right.setStyle( "-fx-background-color: MediumSeaGreen;" );
// GridPane
GridPane gridPane = new GridPane();
gridPane.addRow( 0 , left , center , right ); // Add these widgets in first row (annoying zero-based counting means index 0 is row 1).
gridPane.setStyle( "-fx-grid-lines-visible: true ;" ); // Add lines to the edges of each cell (row/column) in the grid. Useful for learning and debugging. https://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html#gridpane
// Grid constraints
ColumnConstraints column1 = new ColumnConstraints();
column1.setHgrow( Priority.SOMETIMES ); // Extra space alloted to this column.
ColumnConstraints column2 = new ColumnConstraints( 500 ); // Fixed width of 500 pixels.
ColumnConstraints column3 = new ColumnConstraints();
column3.setHgrow( Priority.SOMETIMES );// Extra space alloted to this column.
gridPane.getColumnConstraints().addAll( column1 , column2 , column3 ); // first column gets any extra width
// Render
var scene = new Scene( gridPane , 1000 , 150 );
stage.setScene( scene );
stage.setTitle( "Example of JavaFX GridPane, by Basil Bourque" );
stage.show();
}
public static void main ( String[] args )
{
launch();
}
}
Screenshot of the app running. Notice how the left and right get remaining space of 250 pixels each. We set the window (Stage) to 1,000 pixels, and fixed the width of the center piece to 500 pixels. That leaves 500 pixels remaining to allocate. Both left and right cells were set to the same priority level, so they split the space evenly between them: 500/2 = 250 pixels each.
If the user narrows the width of the window to 600 pixels, the left and right cells will be 50 pixels each: 600 - 500 = 100, 100/2 = 50 pixels each.
Generally I would recommend posting code rather than attempting to describe it. For example this mre can represent your question:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage stage) throws Exception {
Button leftBtn = new Button("Left");
Button centerBtn = new Button("Center");
centerBtn.widthProperty().addListener((obs, oldValue,newValue)-> {
//change the logic as needed
leftBtn.setPrefWidth(newValue.doubleValue() >= 600 ? 200 : 250);
});
centerBtn.setPrefSize(600, 0);
Button rightBtn = new Button("Right");
Pane root = new BorderPane(centerBtn, null, rightBtn, null, leftBtn);
root.setPrefSize(1000, 150);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This also makes helping much easier. For example a solution with HBox as proposed in the comments just requires minor changes in the mre (action box added to the center button to change its width):
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
public class Main extends Application {
private static final double MIN = 300, MAX = 700, DELTA = 100;
private Button centerBtn;
#Override
public void start(Stage stage) throws Exception {
Button leftBtn = new Button("Left");
HBox.setHgrow(leftBtn, Priority.NEVER);
centerBtn = new Button("Click to change width");
HBox.setHgrow(leftBtn, Priority.NEVER);
centerBtn.widthProperty().addListener((obs, oldValue,newValue)-> {
//change the logic as needed
leftBtn.setPrefWidth(newValue.doubleValue() >= 600 ? 200 : 250);
});
centerBtn.setPrefSize(600, 0);
centerBtn.setOnAction(e-> changeCenterBtnWidth());
Button rightBtn = new Button("Right");
HBox.setHgrow(rightBtn, Priority.ALWAYS);
Pane root = new HBox(leftBtn,centerBtn,rightBtn);
root.setPrefSize(1000, 150);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private void changeCenterBtnWidth() {
double newWidth = centerBtn.getWidth() + DELTA;
newWidth = newWidth < MAX ? newWidth : MIN;
centerBtn.setPrefWidth(newWidth);
}
public static void main(String[] args) {
launch(args);
}
}
Demonstrating a solution based on GridPane rquires only some samll changes:
public void start(Stage stage) throws Exception {
Button leftBtn = new Button("Left");
centerBtn = new Button("Click to change width");
centerBtn.widthProperty().addListener((obs, oldValue,newValue)-> {
//change the logic as needed
leftBtn.setPrefWidth(newValue.doubleValue() >= 600 ? 200 : 250);
});
centerBtn.setPrefSize(600, 0);
centerBtn.setOnAction(e-> changeCenterBtnWidth());
Button rightBtn = new Button("Right");
GridPane root = new GridPane();
root.add(leftBtn,0, 0);
root.add(centerBtn,1, 0);
root.add(rightBtn,2, 0);
root.setPrefSize(1000, 150);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}

JavaFX FlowPane within ScrollPane, dynamically adjust scrollpane's content and size

I currently have a ScrollPane with a FlowPane as content. The FlowPane currently initializes with no children nodes, a fixed width and a pref/min height (but no max height).
While adding items to the FlowPane at runtime (I click some UI element and something is added to the FlowPane), the ScrollPane should adjust its height in the case that the addition to the FlowPane no longer fits.
I don't understand how to set the height of the flowPane and ScrollPane so that this works - if that's the problem to begin with. At the moment, whenever the addition to the FlowPane doesn't fit its initial height, the content is added, but not visible. The scrollbar belonging to the ScrollPane never adjusts its height - if it did, I could just scroll further down and see the content.
Let's say I have a ScrollPane with some width and height, some viewport width/height, and a FlowPane with some width/height - What should my settings be for the min/pref/max sizes? How can I make a scrollPane adjust its scrollbar behaviour or make the content visible?
The ScrollPane's setFitToHeight is already set to true, which didn't seem to change anything.
import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class FlowPaneTest extends Application
{
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception
{
// borderPane rootPane
BorderPane borderPane = new BorderPane();
borderPane.setMinSize(600, 600);
borderPane.setPrefSize(600, 600);
borderPane.setMaxSize(600, 600);
// container for the two scrollPanes below
FlowPane flow = new FlowPane();
borderPane.setRight(flow);
// two scrollPanes, each should resize it's height (width should be fixed) if
// children are added beyond it's current height
ScrollPane top = new ScrollPane();
ScrollPane bottom = new ScrollPane();
FlowPane scrollPaneContent = new FlowPane();
top.setContent(scrollPaneContent);
bottom.setContent(scrollPaneContent);
flow.getChildren().add(top);
flow.getChildren().add(bottom);
borderPane.setOnMouseClicked(new EventHandler<Event>()
{
#Override
public void handle(Event event)
{
Label l = new Label("test");
l.setMinSize(100, 100);
l.setPrefSize(100, 100);
l.setMaxSize(100, 100);
scrollPaneContent.getChildren().add(l);
}
});
// size settings
int width = 300, height = 300;
top.setHvalue(0.5);
top.setMinViewportHeight(height);
top.setPrefViewportHeight(height);
top.setMinViewportWidth(width);
top.setPrefViewportWidth(width);
top.setHbarPolicy(ScrollBarPolicy.ALWAYS);
top.setFitToHeight(true);
top.setMinSize(width, height);
top.setPrefSize(width, height);
top.setMaxWidth(width);
scrollPaneContent.setMinSize(width, height);
scrollPaneContent.setPrefSize(width, height);
scrollPaneContent.setMaxWidth(width);
scrollPaneContent.setPrefHeight(height);
bottom.setMinSize(width, height);
bottom.setPrefSize(width, height);
bottom.setMaxWidth(width);
bottom.setHvalue(0.5);
bottom.setMinViewportHeight(height);
bottom.setPrefViewportHeight(height);
bottom.setMinViewportWidth(width);
bottom.setPrefViewportWidth(width);
bottom.setHbarPolicy(ScrollBarPolicy.ALWAYS);
top.setFitToHeight(true);
bottom.setFitToHeight(true);
// stage
Scene scene = new Scene(borderPane, 600.0, 600.0);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Try to give the ScrollPane pref height and width and add this line
scrollPane.setFitToWidth(true);
Ending up with something similar to this ugly bit of code - It listens to the number of children in the pane and increases the size every time something is added to the list of children:
topSubPane.getChildren().addListener(new ListChangeListener()
{
#Override
public void onChanged(Change c)
{
c.next();
topSubPane.setPrefHeight(topSubPane.getHeight() + 50);
}
});
Works, but feels like an unorthodox hack. Is there really no regular way of doing this?

JavaFX ScrollPane [ setPrefSize, setMinSize, setMaxSize ] not working

I'm writing a GUI application with a ScrollPane, but had some issues with resizing. I extracted the essential code in the following example:
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.scene.layout.VBox;
import javafx.scene.control.ScrollPane;
public class JavaFXExample extends Application {
final int width = 300;
final int height = 300;
#Override
public void start(Stage primaryStage) {
Button b = new Button("This should be at the bottom!");
//this vbox goes inside the scrollpane
VBox boxInScrollPane = new VBox(10);
boxInScrollPane.setAlignment(Pos.BOTTOM_CENTER);
boxInScrollPane.getChildren().add(b);
//main content
ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(boxInScrollPane);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
//Doesn't do anything!
scrollPane.setPrefSize(100, 100);
scrollPane.setMaxSize(100, 100);
scrollPane.setMinSize(100, 100);
Scene scene = new Scene(scrollPane, width, height);
primaryStage.setScene(scene);
primaryStage.show();
//set size of boxInScrollPane to be equal to the viewport
Bounds viewportBounds = scrollPane.getViewportBounds();
double innerWidth = viewportBounds.getMaxX() - viewportBounds.getMinX();
double innerHeight = viewportBounds.getMaxY() - viewportBounds.getMinY();
System.out.println(innerWidth + " " + innerHeight);
boxInScrollPane.setPrefSize(innerWidth, innerHeight);
}
public static void main(String[] args) {
launch(args);
}
}
So I have a window, which contains a ScrollPane, which contains a VBox, which contains a button. The example here, where I resize the scrollpane to be 100x100px in a 300x300px window, is arbitrary. What's important is that when I run this code, I get a scrollpane that fills the entire window! Here's my output:
What's going on here?
The root of the scene is sized to fill the entire scene, irrespective of its min/pref/max size. If you want the ScrollPane to remain 100 pixels wide and 100 pixels high, wrap it in another container (pretty much any container will do); the container will then be resized, but the ScrollPane will respect its layout sizes:
Scene scene = new Scene(new StackPane(scrollPane), width, height);
By default a StackPane centers its content, so this results in
Solution:
Pane pane = new Pane(scrollPane);
Scene scene = new Scene(pane, width, height);
primaryStage.setScene(scene);
primaryStage.show();
From Scene constuctor doc:
Creates a Scene for a specific root Node with a specific size.
Setting ScrollPane as root node will make it resize to given size in constructor so the previous settings will not work.
Solution will be to make a simple pane that will be resized so ScrollPane will be on his own rules.

Frosted Glass Effect in JavaFX?

I'm making an iOS7-themed JavaFX2/FXML project and I was wondering how I could make a Rectangle object have a iOS7-like frosted glass effect.
I'd also like it to have a small shadow. This is tricky, since you might be able to see the shadow behind the semi-transparent object. I'd just like it to be present around the edges.
Is this possible? Here's a picture showing the desired effect (not including the small drop-shadow):
UPDATE: Here's a continuation of the issue. This is going to look amazing :D.
Sample Solution
Run the program below and scroll or swipe up to show the glass pane.
The purpose of the program is just to sample the techniques involved not to act as a general purpose library for the frost effect.
import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.Rectangle2D;
import javafx.scene.*;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
// slides a frost pane in on scroll or swipe up; slides it out on scroll or swipe down.
public class Frosty extends Application {
private static final double W = 330;
private static final double H = 590;
private static final double BLUR_AMOUNT = 60;
private static final Duration SLIDE_DURATION = Duration.seconds(0.4);
private static final double UPPER_SLIDE_POSITION = 100;
private static final Effect frostEffect =
new BoxBlur(BLUR_AMOUNT, BLUR_AMOUNT, 3);
#Override public void start(Stage stage) {
DoubleProperty y = new SimpleDoubleProperty(H);
Node background = createBackground();
Node frost = freeze(background, y);
Node content = createContent();
content.setVisible(false);
Scene scene = new Scene(
new StackPane(
background,
frost,
content
)
);
stage.setScene(scene);
stage.show();
addSlideHandlers(y, content, scene);
}
// create a background node to be frozen over.
private Node createBackground() {
Image backgroundImage = new Image(
getClass().getResourceAsStream("ios-screenshot.png")
);
ImageView background = new ImageView(backgroundImage);
Rectangle2D viewport = new Rectangle2D(0, 0, W, H);
background.setViewport(viewport);
return background;
}
// create some content to be displayed on top of the frozen glass panel.
private Label createContent() {
Label label = new Label("The overlaid text is clear and the background below is frosty.");
label.setStyle("-fx-font-size: 25px; -fx-text-fill: midnightblue;");
label.setEffect(new Glow());
label.setMaxWidth(W - 20);
label.setWrapText(true);
return label;
}
// add handlers to slide the glass panel in and out.
private void addSlideHandlers(DoubleProperty y, Node content, Scene scene) {
Timeline slideIn = new Timeline(
new KeyFrame(
SLIDE_DURATION,
new KeyValue(
y,
UPPER_SLIDE_POSITION
)
)
);
slideIn.setOnFinished(e -> content.setVisible(true));
Timeline slideOut = new Timeline(
new KeyFrame(
SLIDE_DURATION,
new KeyValue(
y,
H
)
)
);
scene.setOnSwipeUp(e -> {
slideOut.stop();
slideIn.play();
});
scene.setOnSwipeDown(e -> {
slideIn.stop();
slideOut.play();
content.setVisible(false);
});
// scroll handler isn't necessary if you have a touch screen.
scene.setOnScroll((ScrollEvent e) -> {
if (e.getDeltaY() < 0) {
slideOut.stop();
slideIn.play();
} else {
slideIn.stop();
slideOut.play();
content.setVisible(false);
}
});
}
// create a frosty pane from a background node.
private StackPane freeze(Node background, DoubleProperty y) {
Image frostImage = background.snapshot(
new SnapshotParameters(),
null
);
ImageView frost = new ImageView(frostImage);
Rectangle filler = new Rectangle(0, 0, W, H);
filler.setFill(Color.AZURE);
Pane frostPane = new Pane(frost);
frostPane.setEffect(frostEffect);
StackPane frostView = new StackPane(
filler,
frostPane
);
Rectangle clipShape = new Rectangle(0, y.get(), W, H);
frostView.setClip(clipShape);
clipShape.yProperty().bind(y);
return frostView;
}
public static void main(String[] args) { launch(args); }
}
Source image
Save this image parallel to the Java source as a file named ios-screenshot.png and have your build system copy it to the target directory for the binary output of the build.
Answers to additional questions
"JDK 8," would that happen to be a requirement of this?
The sample code above is written against JDK 8. Porting it back to JDK 7 by replacing the lambda calls with anonymous inner classes is pretty trivial.
In general, Java 7 is pretty dated for JavaFX work. I advise upgrading at your earliest convenience to work with a Java 8 minimum version.
initiating your Panes with arguments
More convenient constructors for most parent nodes is a Java 8 feature. You can easily convert the Java 8 format:
StackPane stack = new StackPane(child1, child2);
To Java 7:
StackPane stack = new StackPane();
stack.getChildren().setAll(child1, child2);
will this working if the desktop is behind a frosty pane?
Not directly, you can create a new question for that.
Update: Related Questions
User created: JavaFX effect on background to allow the frosted effect to apply to a window over a desktop background.
Another user created: How do I create a JavaFX transparent stage with shadows on only the border? to apply a halo shadow effect around this window.

JavaFX 2.1 Change ScrollPane Scrollbar size

I am trying to figure out how to change a scrollpanes scrollbar size to make it wider in javafx 2.1.
The ScrollBar width is based on the font size of the ScrollPane.
Set the font size of the ScrollPane to something big and (if needed) sent the font size of your the ScrollPane's content node back to something normal.
ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(content);
scrollPane.setStyle("-fx-font-size: 40px;"); // set the font size to something big.
content.setStyle("-fx-font-size: 11px;"); // reset the region's font size to the default.
Here is a complete executable example based on my answer to a previous forum question on the same topic.
import javafx.application.Application;
import javafx.collections.*;
import javafx.scene.*;
import javafx.stage.Stage;
import javafx.scene.chart.*;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Region;
public class BigScrollBars extends Application {
#Override public void start(Stage stage) {
// create a chart.
ObservableList<PieChart.Data> pieChartData =
FXCollections.observableArrayList(
new PieChart.Data("Grapefruit", 13),
new PieChart.Data("Oranges", 25),
new PieChart.Data("Plums", 10),
new PieChart.Data("Pears", 22),
new PieChart.Data("Apples", 30)
);
final PieChart chart = new PieChart(pieChartData);
chart.setTitle("Imported Fruits");
chart.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
chart.setPrefSize(800,600);
// create a scrollpane.
ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(chart);
scrollPane.setStyle("-fx-font-size: 40px;"); // set the font size to something big.
chart.setStyle("-fx-font-size: 11px;"); // reset the region's font size to the default.
// show the scene.
stage.setScene(new Scene(scrollPane, 400, 300));
stage.show();
}
public static void main(String[] args) { launch(args); }
}
The following solution worked for me:
#FXML
private ScrollPane myScrollPane;
// Where you need in your code do the following:
Set<Node> nodes = myScrollPane.lookupAll(".scroll-bar");
for (final Node node : nodes) {
if (node instanceof ScrollBar) {
ScrollBar sb = (ScrollBar) node;
if (sb.getOrientation() == Orientation.VERTICAL) { // HORIZONTAL is another option.
sb.setPrefWidth(40); // You can define your preferred width here.
}
}
}

Categories