JavaFX - Dynamically increase the height of StackPane based on children height - javafx-2

I have a GridPane which contains a StackPane at (1,0). To this StackPane I'll dynamically include other Panes based on some logic. I want this StackPane to automatically
increase the height based on the height of the Pane that is included.
stackPane.heightProperty().addListener( new ChangeListener<Number>(){
#Override
public void changed( ObservableValue<? extends Number> arg0, Number oldVal, Number newVal ){
stackPane.setPrefHeight( newVal.doubleValue() + 230 );
}
} );
This method gets called after I add the Pane to the stackPane. But on the screen it doesn't show the new height. Could this be because of the GridPane's row height?
For that column (where the stackPane is included), I've set the maxHeight to MAX_VALUE and prefHeight to USE_COMPUTED_VALUE

Related

Android: Custom bottom sheet dialog

How can I implement following design functionality with android standard component bottom sheet:
Image when Bottom sheet dialog fragment will appear:
Image when user scrolled to up to view bottom of content:
I will use ViewPager to scrolling header images and RecyclerView to showing descriptions and other informations. And parallax effect to ImageView(which are placed in ViewPager) when scrolling content vertically. Have a minimum height of the ImageView(and ViewPager), user can't collapse fully it (Look to second screenshot, which is user scrolled until the end of content).
I want stop scrolling ImageView when it will reach to minimum height(look to second one Screenshot), but the content of below ImageView should be continue scrolling
This can be done with an if statement in an on scroll view such as shown below:
ScrollView scrollView = findViewById(R.id.scrollView); //Adjust for your code
ImageView imageView = findViewById(R.id.imageView); //Adjust for your code
boolean imageIsHidden = false;
int threshold = 250;
scrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {
#Override
public void onScrollChanged() {
int scrollY = rootScrollView.getScrollY();
if(scrollY >= threshold){
imageIsHidden = true;
//Move image outside of scroll view so it doesn't scroll
}
else if(scrollY < threshold && imageIsHidden){
imageIsHidden = false;
//Move image inside of scroll view so it does scroll
}
}
});
What this does is has a boolean called imageIsHidden and an integer called threshold. Threshold is where you want it to make it disappear. You will need to play around with this value to find a sweet spot.
You will also need to implement moving the image inside and outside of the scroll view as well in the if and if else statement.

BorderPane spacing between nodes

Is it possible to set a spacing between nodes on a BorderPane? The Swing-equivalent would be hgap and vgap on BorderLayout.
I didn't find anything in the documentation and the only viable workaround I can think of would be to selectively set margins on the child nodes to replicate the effect.
Insets insets = new Insets(10);
BorderPane bp = new BorderPane();
Node topNode = new Label("TOP");
bp.setTop(topNode);
BorderPane.setMargin(topNode, insets);
Node centerNode = new Label("CENTER");
bp.setCenter(centerNode);
BorderPane.setMargin(centerNode, insets);
Node bottomNode = new Label("BOTTOM");
bp.setBottom(bottomNode);
BorderPane.setMargin(bottomNode, insets);
Be aware: this will put a spacing of 20 (10 from top and 10 from center) between top and center.
Similar for the spacing between center and bottom.
The documentation
public static void setMargin(Node child, Insets value)
Sets the margin for the child when contained by a border pane. If set, the border pane will lay it out with the margin space around it. Setting the value to null will remove the constraint.
It's possible to set the padding:
In JFX:
<BorderPane>
<padding>
<Insets top="10" right="10" bottom="10" left="10"/>
</padding>
</BorderPane>
In code:
#FXML
private BorderPane borderPane;
...
this.borderPane.setPadding(new Insets(10, 10, 10, 10));

Insert text at the center of a image

I have this code which inserts Image into the center of a borderpane:
private static final ImageView iv;
static {
iv = new ImageView(StartPanel.class.getResource("/com/dx57dc/images/6.jpg").toExternalForm());
}
bpi.setCenter(iv);
And now I have this problem. I have this insert text as a label at the center of the image.
Text inftx = new Text("Infrastructure");
How I can do this?
You can use a StackPane to performed the desired image overlap. The following code can be used on your example:
private static final ImageView iv;
static {
iv = new ImageView(StartPanel.class.getResource("/com/dx57dc/images/6.jpg").toExternalForm());
Text inftx = new Text("Infrastructure");
StackPane pane = new StackPane();
pane.getChildren().add(iv);
pane.getChildren().add(inftx);
pane.setAlignment(Pos.CENTER);
}
As informed on StackPane tutorial:
The StackPane layout pane places all of the nodes within a single stack with each new node added on top of the previous node. This layout model provides an easy way to overlay text on a shape or image or to overlap common shapes to create a complex shape.

JavaFX fullscreen - resizing elements based upon screen size

Is there any way to make fullscreen(and if possible resizing too) to instead of rearranging everything (actually what it does is to rearrange the elements like resizing but to the whole screen) to make an actual fullscreen mode? (like games that what usually do is change screen resolution), so that buttons and text grows accordingly to the size of the screen/window
Also how can I remove the message and the effect on click the "esc" key to exit the fullscreen mode?
EDIT: use this way to make resizeable
#Override public void start(Stage stage) throws Exception{
final int initWidth = 720; //initial width
final int initHeight = 1080; //initial height
final Pane root = new Pane(); //necessary evil
Pane controller = new CtrlMainMenu(); //initial view
controller.setPrefWidth(initWidth); //if not initialized
controller.setPrefHeight(initHeight); //if not initialized
root.getChildren().add(controller); //necessary evil
Scale scale = new Scale(1, 1, 0, 0);
scale.xProperty().bind(root.widthProperty().divide(initWidth)); //must match with the one in the controller
scale.yProperty().bind(root.heightProperty().divide(initHeight)); //must match with the one in the controller
root.getTransforms().add(scale);
final Scene scene = new Scene(root, initWidth, initHeight);
stage.setScene(scene);
stage.setResizable(true);
stage.show();
//add listener for the use of scene.setRoot()
scene.rootProperty().addListener(new ChangeListener<Parent>(){
#Override public void changed(ObservableValue<? extends Parent> arg0, Parent oldValue, Parent newValue){
scene.rootProperty().removeListener(this);
scene.setRoot(root);
((Region)newValue).setPrefWidth(initWidth); //make sure is a Region!
((Region)newValue).setPrefHeight(initHeight); //make sure is a Region!
root.getChildren().clear();
root.getChildren().add(newValue);
scene.rootProperty().addListener(this);
}
});
}
There are a couple of ways to resize your UI.
Scale by Font Size
You can scale all controls by setting -fx-font-size in the .root of your scene's style sheet.
For example, if you apply the following stylesheet to your scene, then all controls will be doubled in size (because the default font size is 13px).
.root {
-fx-font-size: 26px;
}
The above will work to scale controls, which is fine for things which are completely control based, but not so good for things which are graphic and shape based.
Scale by Transform
Apply a Scale transform pivoted at (0,0) to your scene's root node.
Scale scale = new Scale(scaleFactor, scaleFactor);
scale.setPivotX(0);
scale.setPivotY(0);
scene.getRoot().getTransforms().setAll(scale);
To scale a game I developed which includes graphics and various shapes, I used a letter boxing technique which sized the game window to a constant aspect ratio, (similar to the letter boxing you see when you watch a 4:3 tv show on a 16:9 screen).
The SceneSizeChangeListener in the code below listens for changes to the scene size and scales the content of the scene appropriate to the available scene size.
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.transform.Scale;
import javafx.stage.Stage;
import org.jewelsea.games.supersnake.layout.LayoutController;
import java.io.IOException;
import java.util.ResourceBundle;
/* Main JavaFX application class */
public class SuperSnake extends Application {
public static void main(String[] args) { launch(args); }
#Override public void start(final Stage stage) throws IOException {
FXMLLoader loader = new FXMLLoader(
getClass().getResource("layout/layout.fxml"),
ResourceBundle.getBundle("org.jewelsea.games.supersnake.layout.text")
);
Pane root = (Pane) loader.load();
GameManager.instance().setLayoutController(loader.<LayoutController>getController());
Scene scene = new Scene(new Group(root));
stage.setScene(scene);
stage.show();
GameManager.instance().showMenu();
letterbox(scene, root);
stage.setFullScreen(true);
}
private void letterbox(final Scene scene, final Pane contentPane) {
final double initWidth = scene.getWidth();
final double initHeight = scene.getHeight();
final double ratio = initWidth / initHeight;
SceneSizeChangeListener sizeListener = new SceneSizeChangeListener(scene, ratio, initHeight, initWidth, contentPane);
scene.widthProperty().addListener(sizeListener);
scene.heightProperty().addListener(sizeListener);
}
private static class SceneSizeChangeListener implements ChangeListener<Number> {
private final Scene scene;
private final double ratio;
private final double initHeight;
private final double initWidth;
private final Pane contentPane;
public SceneSizeChangeListener(Scene scene, double ratio, double initHeight, double initWidth, Pane contentPane) {
this.scene = scene;
this.ratio = ratio;
this.initHeight = initHeight;
this.initWidth = initWidth;
this.contentPane = contentPane;
}
#Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) {
final double newWidth = scene.getWidth();
final double newHeight = scene.getHeight();
double scaleFactor =
newWidth / newHeight > ratio
? newHeight / initHeight
: newWidth / initWidth;
if (scaleFactor >= 1) {
Scale scale = new Scale(scaleFactor, scaleFactor);
scale.setPivotX(0);
scale.setPivotY(0);
scene.getRoot().getTransforms().setAll(scale);
contentPane.setPrefWidth (newWidth / scaleFactor);
contentPane.setPrefHeight(newHeight / scaleFactor);
} else {
contentPane.setPrefWidth (Math.max(initWidth, newWidth));
contentPane.setPrefHeight(Math.max(initHeight, newHeight));
}
}
}
}
Here is a screenshot where you can see the letterboxing and scaling taking effect. The green grass in the middle is the main game content screen and scales up and down to fit the available screen area. The wood texture around the outside provides a flexibly sized border which fills in the area where the black letterbox bars would normally be if you were watching a tv program at a different aspect ratio to your screen. Note that the background in the screenshot below is blurry at the title page because I make it so, when the game starts, the blur effect is removed and the view is crisp regardless of the size.
Windowed version:
Scaled full screen version:
You might think that the scaling method above might make everything go all blocky and pixelated, but it doesn't. All font's and controls scale smoothly. All standard drawing and graphic commands and css based styles scale smoothly as they are all vector based. Even bitmapped images scale well because JavaFX uses fairly high quality filters when scaling the images.
One trick to get good scaling on images is to provide high resolution images, so that when the screen scales up, the JavaFX system has more raw data to work from. For example, if the preferred window size for an app is quarter of the screen size and it contains a 64x64 icon, instead use a 128x128 icon, so that when the app is put in full screen and all elements scaled, the scaler has more raw pixel data samples to use for interpolating values.
The scaling is also fast as it is hardware accelerated.
how can I remove the message and the effect on click the "esc" key to exit the fullscreen mode?
It's not possible to remove the full screen exit message in JavaFX 2.2, it will be possible in JavaFX 8:
RT-15314 Allow trusted apps to disable the fullscreen overlay warning and disable the "Exit on ESC" behavior
It will be nice when that is done, because then my games won't have that "look at me - I look like a beta" feel about them.
"Also how can I remove the message and the effect on click the "esc" key to exit the fullscreen mode?"
Use this code :
stage.setFullScreenExitHint("");
It will change the string message "Press Esc to quit Fullscreen mode" into empty string so it will not show up.
You may copy this into JavaFXApplication
Dimension resolution = Toolkit.getDefaultToolkit().getScreenSize();
double width = resolution.getWidth();
double height = resolution.getHeight();
double w = width/1280; // your window width
double h = height/720; // your window height
Scale scale = new Scale(w, h, 0, 0);
root.getTransforms().add(scale);

javafx 2.0 how to add scroll bar in Accordion

the accordion height will increase once the titled pane expanded.
but since the window is a fixed height window, if the height of accordion is bigger than the window height,the content of bottom titled pane will be clipped off.
so how can i show a vertical scroll bar to display those titled panes
is there any way to add a scroll bar in accordion
or i need to put accordion in a control which may show scroll bar when accordion exceed the height the outer control ?
thanks
Add a scroll pane inside the accordion and set the scroll pane size to the size of the accordion minus the heights of the bars. Your scroll pane's contents can then exceed the size of the accordion.
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
Accordion accord=new Accordion();
ScrollPane scroll=new ScrollPane();
scroll.setPrefHeight(accord.getHeight());
scroll.prefWidth(accord.getWidth());
TitledPane title=new TitledPane();
title.setText("Accordian");
title.setContent(scroll);
accord.getPanes().add(title);
root.getChildren().add(accord);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Scroll Pane");
primaryStage.setScene(scene);
primaryStage.show();
}

Resources