Button positioning using HBox javafx - javafx

I am trying to place my two button directly under my label and have everything centered on my form. Currently everything is just printed on one line.
#Override
public void start(Stage primaryStage) throws Exception{
HBox hb = new HBox();
hb.setSpacing(15);
hb.setPadding(new Insets(15, 20, 5, 10));
hb.setAlignment(Pos.CENTER);
Label label = new Label("Greetings! Would you like to purchase cruise ticket for a family of two?");
hb.getChildren().add(label);
button1 = new Button("Yes");
hb.getChildren().add(button1);
button1.setOnAction(this);
button2 = new Button("No");
hb.getChildren().add(button2);
button2.setOnAction(this);
Scene scene = new Scene(hb, 550, 250);
primaryStage.setTitle("Cruise for two!");
primaryStage.setScene(scene);
primaryStage.show();
}

For more information on the many layout options available in JavaFX, Oracle provides a great tutorial that I recommend you review!
The HBox will always arrange its children in a horizontal row. By adding your Label to the HBox, JavaFX is doing what you're telling it to.
You also have a VBox, which arranges nodes vertically. Within the VBox, add your Label and then your HBox; they will be arranged with the HBox under the Label.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
private Button button1;
private Button button2;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
VBox root = new VBox(5);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
HBox hb = new HBox();
hb.setSpacing(15);
hb.setPadding(new Insets(15, 20, 5, 10));
hb.setAlignment(Pos.CENTER);
Label label = new Label("Greetings! Would you like to purchase cruise ticket for a family of two?");
root.getChildren().add(label);
button1 = new Button("Yes");
hb.getChildren().add(button1);
button2 = new Button("No");
hb.getChildren().add(button2);
root.getChildren().add(hb);
Scene scene = new Scene(root, 550, 250);
primaryStage.setTitle("Cruise for two!");
primaryStage.setScene(scene);
primaryStage.show();
}
}
RESULT:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity">
<children>
<Label text="Label" />
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity">
<children>
<Button mnemonicParsing="false" text="Button" />
<Button mnemonicParsing="false" text="Button" />
</children>
</HBox>
</children>
</VBox>
</children>
</StackPane>

Related

Drag edges of imageview to resize in JavaFX [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 months ago.
Improve this question
Dears, I'm about to make a Java/JavaFX for my own experience. What this program is supposed to do is to load some images and do some resize and labeling on them. I need to implement resize functionality on imageview which I create dynamically at runtime in JavaFX. I don't know how to do that. Can someone give me a hand?
Here it is my code:
FXML file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1024.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.me.code.HelloController">
<children>
<VBox fx:id="imageList" layoutY="44.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="677.0" prefWidth="1024.0" />
<Button layoutX="904.0" layoutY="733.0" mnemonicParsing="false" onAction="#finishButtonHandler" text="Finish" />
<ToolBar layoutY="4.0" prefHeight="40.0" prefWidth="319.0">
<items>
<Button mnemonicParsing="false" onAction="#rightButtonHandler" text="Right" />
<Button mnemonicParsing="false" onAction="#leftButtonHandler" text="Left" />
<Button mnemonicParsing="false" onAction="#addImageButtonHandler" text="Add Image" />
</items>
</ToolBar>
</children>
</AnchorPane>
Controller file:
package com.me.code;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
public class HelloController implements Initializable {
#FXML
private VBox imageList;
#FXML
void addImageButtonHandler(ActionEvent event) {
Image img = new Image(getClass().getResourceAsStream("sample_image.jpg"), 100, 100, false, false);
ImageView imageView = new ImageView();
imageView.setImage(img);
imageView.toFront();
imageView.setVisible(true);
imageView.setPreserveRatio(true);
imageView.setFitHeight(100);
imageView.setFitWidth(100);
imageView.fitHeightProperty().bind(imageList.heightProperty());
imageList.getChildren().add(imageView);
}
#FXML
void finishButtonHandler(ActionEvent event) {
}
#FXML
void leftButtonHandler(ActionEvent event) {
}
#FXML
void rightButtonHandler(ActionEvent event) {
}
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
}
Resizing with polygon shape
As you can see the image can be stretched but is resizable . The trick is bind bidrectionally x and y translate property from group object (parent of polygon) to FitHeightProperty and FitWidth property from imageview object
this is a single functional javafx app you can try
App.java
public class App extends Application {
private double startX;
private double startY;
#Override
public void start(Stage stage) throws Exception {
ImageView imageView = new ImageView("https://ioppublishing.org/wp-content/uploads/2017/03/cat-web-cc0.jpg");
imageView.setFitHeight(436);
imageView.setFitWidth(560);
Group handler = makeHandler();
handler.translateXProperty().bindBidirectional(imageView.fitWidthProperty());
handler.translateYProperty().bindBidirectional(imageView.fitHeightProperty());
Group imageGroup = new Group(imageView, handler);
StackPane stackPane = new StackPane(imageGroup);
Scene scene = new Scene(stackPane, 800, 600);
stage.setTitle("Resizing image");
stage.setScene(scene);
stage.show();
}
private Group makeHandler() {
Polygon polygon = new Polygon();
Group group = new Group(polygon);
polygon.getPoints().addAll(0.0, 0.0, 0.0, -20.0, -20.0, 0.0);
polygon.setStroke(Color.BLACK);
polygon.setFill(Color.AZURE);
polygon.setStrokeWidth(2);
polygon.setStrokeType(StrokeType.INSIDE);
group.setOnMousePressed(e -> {
startX = group.getLayoutX() - e.getX();
startY = group.getLayoutY() - e.getY();
});
group.setOnMouseDragged(e -> {
group.setTranslateX(group.getTranslateX() + e.getX() + startX);
group.setTranslateY(group.getTranslateY() + e.getY() + startY);
});
return group;
}
}

More efficient way to add Panes to an HBox?

I am working on a project that is going to involve adding panes (or hboxes if that works better) to a very wide HBox. I set it up in an fxml pretty easily but I'm already going to have to make a few of these and I would love to avoid all the copying pasting. So I figured I should try and use a for loop to populate the HBox but for whatever reason it is not working. I'm in the very beginning steps so my code is very simple and straight forward.
This is the basic sample I'm trying to recreate
<HBox>
<children>
<Pane fx:id="pane0" prefHeight="200.0" prefWidth="200.0">
<children>
<Button layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
</children></Pane>
<Pane fx:id="pane1" prefHeight="200.0" prefWidth="200.0">
<children>
<Button layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
</children></Pane>
<Pane fx:id="pane2" prefHeight="200.0" prefWidth="200.0">
<children>
<Button layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
</children></Pane>
</children>
</HBox>
So to create it dynamically (and for clarity) I created a class for the HBox and the panes. For now each pane just has a button but they will undergo further customization once this code works. Same with the HBox.
Here's the HBox
public class HBoxTestClass {
#FXML
HBox hBox = new HBox();
public HBoxTestClass(){
}
#FXML
public void initialize(){
populateHBox();
}
private void populateHBox(){
for (int i = 0; i < 3; i++){
hBox.getChildren().add(new TestPane());
hBox.setSpacing(10);
}
}
}
its fxml
<HBox fx:id="hBox" xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="sample.HBoxTestClass"
prefHeight="400.0" prefWidth="600.0">
</HBox>
The pane class and its fxml
public class TestPane extends Pane{
#FXML Pane testPane = new Pane();
#FXML Button button = new Button();
public TestPane(){
}
#FXML
private void initialize(){
button.setText("Click Me!");
}
}
<Pane fx:id="testPane" xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="sample.TestPane"
prefHeight="200.0" prefWidth="200.0">
<children>
<Button fx:id="button" layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
</children>
</Pane>
So my very simple code above just produces a blank, wide screen with no panels in it. I put a console print in the constructor of my TestPane class so I know it's getting called but still nothing appears. Any advice? Thanks
I am not sure what you are doing in your code incorrectly. Code like #FXML Pane testPane = new Pane(); should look like #FXML Pane testPane;. I am not sure how code like #FXML
public void initialize(){ is being called in your program. Try to follow this MCVE.
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication363 extends Application
{
#Override
public void start(Stage stage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
Controller
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
/**
*
* #author blj0011
*/
public class FXMLDocumentController implements Initializable
{
#FXML
private HBox hBox;
#Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
for (int i = 0; i < 5; i++) {
StackPane stackPane = new StackPane(new Label("Label: " + i));
hBox.getChildren().add(stackPane);
}
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.HBox?>
<HBox fx:id="hBox" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication363.FXMLDocumentController" />

How to fill text vertically in javaFX?

I've tried stretch height and width out but only width can show text horizontally, not vertically.
Below is what I've tried.
Label label5 = new Label("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
HBox hbox5 = new HBox();
label5.setMinHeight(Region.USE_COMPUTED_SIZE);
hbox5.getChildren().add(label5);
hbox5.setAlignment(Pos.TOP_CENTER);
hbox5.setMinHeight(Region.USE_COMPUTED_SIZE);
but It seems doesn't work.
Please let me know if I missed something Thank you!
you can wrapText(true) and rotate(90.0) your Label and worry less about the rest?
Label l = new Label("some long text goes here - ");
l.setWrapText(true);
l.setRotate(90.0);
The key is making sure you use a Monospaced font.
Code Version:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication42 extends Application {
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
Label label = new Label("Hello World");
label.setFont(Font.font("Monospaced"));
label.setWrapText(true);
label.setMinWidth(1);
label.setPrefWidth(1);
label.setMaxWidth(1);
root.getChildren().add(label);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
FXML Version:
?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label layoutX="296.0" layoutY="81.0" prefHeight="198.0" prefWidth="0.0" text="HELLO WORLD" wrapText="true" />
</children>
</Pane>

JavaFx ImageView won't resize on fitWidthProperty bind to VBox

I am trying to re-size an image so it fits (scaled) in the space allotted by a SplitPane (for workaround suggestions: this image will change when running the program, it should be generated from the text). The ImageView I'm using currently changes the location of the SplitPane Divider. The divider can never cause the ImageView to decrease past the size of the image.
Two images showing this behavior.
Linking the ImageView fitWidthProperty to a VBox has not given me the resize behavior I expected. Increasing the ImageView's size does work (where it is fixed without the binding), but the image never grows, it just gets borders around it.
My MWE:
sample.fxml:
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<SplitPane orientation="HORIZONTAL" xmlns:fx="http://javafx.com/fxml">
<TextArea fx:id="textArea"/>
<VBox fx:id="vBox" alignment="CENTER">
<HBox fx:id="hBox" alignment="CENTER">
<ImageView fx:id="imageView"/>
</HBox>
</VBox>
</SplitPane>
Controller.java:
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
public class Controller {
#FXML
private TextArea textArea = new TextArea();
#FXML
private VBox vBox = new VBox();
#FXML
private HBox hBox = new HBox();
#FXML
private ImageView imageView = new ImageView();
public Controller() {
imageView.fitWidthProperty().bind(vBox.widthProperty());
imageView.fitHeightProperty().bind(hBox.heightProperty());
}
public void start() {
textArea.setText("text");
Image image = new Image("https://www.google.nl/images/srpr/logo11w.png");
imageView.setImage(image);
}
}
and Main.java:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(final Stage primaryStage) throws Exception {
final Controller controller = new Controller();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("sample.fxml"));
fxmlLoader.setController(controller);
final Parent root = fxmlLoader.load();
primaryStage.setTitle("MWE");
final Scene scene = new Scene(root, 640, 480);
primaryStage.setScene(scene);
primaryStage.show();
controller.start();
}
public static void main(String[] args) {
launch(args);
}
}
You can try binding the ImageView's fitWidthProperty() to the SplitPane's divider position property.
A binding similar to this should work :
imageView.fitWidthProperty().bind(Bindings.subtract(1,
splitPane.getDividers().get(0).positionProperty())
.multiply(splitPane.widthProperty());
this is my sample for you!
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<StackPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center">
<SplitPane fx:id="splitpane">
<VBox fx:id="left" prefWidth="300" prefHeight="200" style="-fx-background-color: antiquewhite">
<ImageView fx:id="image1" preserveRatio="true" pickOnBounds="true">
<image>
<Image url="#/sample/test.jpg"/>
</image>
</ImageView>
</VBox>
<VBox fx:id="right" prefWidth="300" prefHeight="300" style="-fx-background-color: aquamarine">
<ImageView fx:id="image2" preserveRatio="true" pickOnBounds="true">
<image>
<Image url="#/sample/test.jpg"/>
</image>
</ImageView>
</VBox>
</SplitPane>
package sample;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.SplitPane;
import javafx.scene.image.ImageView;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable {
#FXML
ImageView image1;
#FXML
ImageView image2;
#FXML
SplitPane splitpane;
#Override
public void initialize(URL location, ResourceBundle resources) {
splitpane.getDividers().get(0).positionProperty().addListener((observable, oldValue, newValue) -> {
System.out.println(newValue);
int w = 600;
double w1 = w * newValue.doubleValue();
double w2 = w - w1;
image1.setFitWidth(w1);
image2.setFitWidth(w2);
});
}
}

Show / Hide a Node within a stage

I am aware that there are already answers for this question but somehow, it was not able to solve my problem.
When I click the textfield in IMAGE1, I want the keyboard FXML(IMAGE2) to appear as is in IMAGE3. But the thing is, I can't seem to find the solution. How do I do this?
I need your help please.
IMAGE1
IMAGE2
IMAGE3
I am experimenting with something similar, here is what I came up with (one of many possible solutions):
You need to wrap your main layout (IMAGE1) in a StackPane. Its usage is to overlay what needs be overlaid (the keyboard in your case). The keyboard is placed in another pane (a VBox in the following example). The VBox:
is placed in the StackPane after the main layout to sit on top of it
is given a maximum height, so that it doesn't fill the entire window
is given a translateY equal to the height
and bottom alignment
The relevant code n FXML:
<VBox fx:id="statusContainer" maxHeight="100.0" prefHeight="100.0"
translateY="100.0" StackPane.alignment="BOTTOM_LEFT" />
This will always be outside of the view. Toggling the keyboard requires 2 TranslateTransitions (can it be done with 1, I wonder?), one to move the keyboard up, one down.
The example code:
1) Java:
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Test1 extends Application
{
#FXML private VBox statusContainer;
private TranslateTransition showStatus;
private TranslateTransition hideStatus;
boolean showsStatus = false;
#Override
public void start(Stage primaryStage) {
try {
StackPane page = (StackPane) FXMLLoader.load(this.getClass().getResource("test1.fxml"));
Scene scene = new Scene(page);
primaryStage.setTitle(this.getClass().getName());
primaryStage.setScene(scene);
primaryStage.sizeToScene();
primaryStage.show();
}
catch (IOException e) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, e);
}
}
#FXML void initialize() {
showStatus = new TranslateTransition(Duration.millis(250), statusContainer);
showStatus.setByY(-100.0);
showStatus.setOnFinished(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
showsStatus = true;
}
});
hideStatus = new TranslateTransition(Duration.millis(250), statusContainer);
hideStatus.setByY(100.0);
hideStatus.setOnFinished(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
showsStatus = false;
}
});
}
public void toggleStatus() {
if( showsStatus ) {
showStatus.stop();
hideStatus.play();
}
else {
hideStatus.stop();
showStatus.play();
}
}
public static void main(String[] args) {
launch(args);
}
}
2) FXML (call it test1.fxml to match the code):
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<StackPane id="StackPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="fancymsg.FancyMsg1">
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Button mnemonicParsing="false" onAction="#toggleStatus" text="Status" AnchorPane.leftAnchor="50.0" AnchorPane.topAnchor="100.0" />
</children>
</AnchorPane>
<VBox fx:id="statusContainer" maxHeight="100.0" prefHeight="100.0" translateY="100.0" StackPane.alignment="BOTTOM_LEFT" />
</children>
<stylesheets>
<URL value="#test1.css" />
</stylesheets>
</StackPane>
3) The CSS for the VBox to stand out (call it test1.css):
#statusContainer {
-fx-background-color: -fx-color;
}
An mcve version of this answer
can be found here

Resources