Using JavaFX: Is It Possible to Put A GridPane in an Alert Dialog Box? - javafx

I have an alert box that is populated with text and for formatting reasons I was wondering if I could somehow put a GridPane inside this Alert box so all the text is spaced out correctly.
If it is not possible to do this with GridPane is there some other way of formatting text I could use?

Yes, you can set any node as content of a dialog box.
alert.getDialogPane().setContent(grid);
Here is a sell/buy alert for frozen orange contracts formatted as grid content.
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class GridAlert extends Application {
#Override
public void start(Stage stage) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("Frozen Orange Juice Contracts");
GridPane grid = new GridPane();
grid.addRow(0, new Label("Sell"), new Label("142"));
grid.addRow(1, new Label("Buy"), new Label("29"));
grid.setHgap(30);
ColumnConstraints right = new ColumnConstraints();
right.setHalignment(HPos.RIGHT);
grid.getColumnConstraints().setAll(new ColumnConstraints(), right);
alert.getDialogPane().setContent(grid);
Button showAlert = new Button("Show Alert");
showAlert.setOnAction(event -> alert.showAndWait());
HBox layout = new HBox(10);
layout.getChildren().addAll(
showAlert
);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
alert.initOwner(stage);
alert.initModality(Modality.WINDOW_MODAL);
}
public static void main(String[] args) {
launch();
}
}

Related

I'm trying to figure out how to make my VBox inside a BorderPane expand with the BorderPane/Stage, but still stay within a certain bounds

I am trying to figure out how to make my VBox, only go to the size of 300 pixel's wide, but i would like to have it at say 250 pixels wide when the program is initialized, then when the user clicks full screen, I want it to expand, but not necessarily with the entire space it would have. I want it to only go to 300 pixels (and have the 3 buttons inside do the same thing) but I'm not sure how to do that. I'm having trouble determining PrefSize and CompSize actual meanings and uses. Any help would be great.
I am also having kind of the same problem with the Label, inside the HBox, that is inside a SplitPane, that is inside a BorderPane. Any explanation of why what you are suggesting will work, will help me with future problems like this. Thank you
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class MainStarUI extends Application {
#Override
public void start(Stage primaryStage){
MenuBar mainMenuOne = addMenuBar();
VBox leftVBoxOne = addVbox();
//AnchorPane midPaneOne = addAnchorPane();
//HBox topHBoxOne = addHBox();
SplitPane midSplitPane = addSplitPane();
BorderPane mainPane = new BorderPane();
mainPane.setTop(mainMenuOne);
mainPane.setLeft(leftVBoxOne);
mainPane.setCenter(midSplitPane);
primaryStage.setMinWidth(1440);
primaryStage.setMinHeight(900);
Scene mainScene = new Scene(mainPane);
primaryStage.setScene(mainScene);
primaryStage.show();
}
public MenuBar addMenuBar(){
Menu menuOne = new Menu("File");
Menu menuTwo = new Menu("Edit");
Menu menuThree = new Menu("Help");
Menu menuFour = new Menu("Exit");
MenuItem menuItemOne = new MenuItem("File");
MenuItem menuItemTwo = new MenuItem("Open");
MenuItem menuItemThree = new MenuItem("Exit");
menuOne.getItems().add(menuItemOne);
menuOne.getItems().add(menuItemTwo);
menuFour.getItems().add(menuItemThree);
MenuBar mainMenuOne = new MenuBar();
mainMenuOne.getMenus().add(menuOne);
mainMenuOne.getMenus().add(menuTwo);
mainMenuOne.getMenus().add(menuThree);
mainMenuOne.getMenus().add(menuFour);
mainMenuOne.maxHeight(25);
mainMenuOne.minHeight(25);
return mainMenuOne;
}
public VBox addVbox(){
VBox leftVBox = new VBox();
leftVBox.setMinWidth(300);
leftVBox.setPrefWidth(300);
leftVBox.setPadding(new Insets(15));
leftVBox.setSpacing(20);
leftVBox.setStyle("-fx-background-color: #336699;");
Button firstButton = new Button("Ships, Components, Items & Weaponry");
firstButton.setMinSize(270, 270);
firstButton.setMaxSize(270, 270);
Button secondButton = new Button("Trading, Mining, Refining & Commodities");
secondButton.setMinSize(270, 270);
secondButton.setMaxSize(270,270);
Button thirdButton = new Button("Star Systems, Planets, Moons & Locations");
thirdButton.setMinSize(270,270);
thirdButton.setMaxSize(270, 270);
leftVBox.getChildren().addAll(firstButton, secondButton, thirdButton);
return leftVBox;
}
public HBox addHBox(){
Image logoImage = new Image("SCImages/TaktikalLogo1.jpg");
ImageView logoImageView = new ImageView();
logoImageView.setImage(logoImage);
logoImageView.setPreserveRatio(false);
logoImageView.setFitWidth(160);
logoImageView.setFitHeight(160);
logoImageView.setSmooth(true);
logoImageView.setCache(true);
Label topLabel = new Label("STAR CITIZEN INFONET & DATABASE");
topLabel.setFont(new Font("Arial", 48));
topLabel.setTextFill(Color.WHITE);
topLabel.setMinHeight(160);
topLabel.setMaxHeight(160);
HBox topHBox = new HBox();
topHBox.setStyle("-fx-background-color: black");
topHBox.setMinHeight(180);
topHBox.setMaxHeight(180);
topHBox.setPrefWidth(1090);
topHBox.getChildren().addAll(logoImageView, topLabel);
topHBox.setPadding(new Insets(10));
topHBox.setSpacing(10);
return topHBox;
}
public SplitPane addSplitPane(){
HBox topHBoxOne = addHBox();
AnchorPane anchorSplitPane = new AnchorPane();
SplitPane mainSplitPane = new SplitPane();
mainSplitPane.setOrientation(Orientation.VERTICAL);
mainSplitPane.setDividerPosition(1, 200);
mainSplitPane.setPrefSize(1090, 850);
mainSplitPane.getItems().addAll(topHBoxOne, anchorSplitPane);
return mainSplitPane;
}
public static void main(String[] args) {
launch(args);
}
}
I actually put my VBox inside an AnchorPane, and attached it to the anchors, and everything worked perfectly after I set my preferred height and width.

How to use modal dialog in this case?

I have a question. I need to make a GridPane with a directory choose that will then lead me to a modal dialog showing photos. I cannot figure how to do the modal dialog that also has to be a GridPane or a HBox...so the question is , how do I get to show a Modal Dialog after selecting the Folder and pressing the "Show" Button... Thanks a lot!
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
public class FotoView extends Application {
#Override
public void start(Stage primaryStage) {
TextField tf = new TextField();
Button b1 = new Button("Search");
Button b2 = new Button("Show");
DirectoryChooser dc = new DirectoryChooser();
GridPane gp = new GridPane();
gp.add(tf, 0 , 0);
gp.add(b1, 1, 0);
gp.add(b2, 0, 1);
b1.setOnAction(e-> dc.showDialog(primaryStage));
primaryStage.setScene(new Scene(gp)) ;
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
} ```
Below is a quick example where a first window has a button that opens up a DirectoryChooser. Once a directory has been selected a second smaller window opens up with the Modality set to APPLICATION_MODAL. In this second window you could add the image(s) that you load and add them to the GridPane.
import java.io.File;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.DirectoryChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(final String[] args) {
launch(args);
}
#Override
public void start(final Stage aStage) throws Exception {
final HBox root = new HBox();
final Button browseBtn = new Button("Click to open a Directory chooser");
root.getChildren().add(browseBtn);
browseBtn.setOnAction(e -> {
final DirectoryChooser chooser = new DirectoryChooser();
final File dir = chooser.showDialog(aStage);
openNewModalStage(aStage, dir);
});
final Scene scene = new Scene(root, 500, 500);
aStage.setScene(scene);
aStage.show();
}
private void openNewModalStage(final Stage aStage, final File aDirectory) {
final Stage stage = new Stage();
final GridPane grid = new GridPane();
final Scene scene = new Scene(grid);
grid.setStyle("-fx-background-color:black");
grid.setPrefWidth(400);
grid.setPrefHeight(400);
// get your images from 'aDirectory' and add them to your grid pane.
stage.setScene(scene);
// set the new windows Modality.
stage.initModality(Modality.APPLICATION_MODAL);
stage.show();
}
}
This way you would only need the one button and the dialog would show as soon as you've selected a directory. However, if you would still want a Search and Show button then just store the directory as a variable and add a listener on the 'show' button and move the openNewModalStage call to that one and remove the second argument.
Edit:
Also, depending on how many images and exactly what you want to display in the modal window, you might want to reconsider the GridPane and use a TilePane, or an hbox/vbox inside of a scroll pane. It's just a thought but I don't know what you will be doing with the GridPane.

Javafx custom cursor reverts to system when hovering over background

I have added a default cursor:
someScene.setCursor(getSomeCursor());
This is working. I have this cursor-code working everywhere in my application, and it looks fine. But whenever I hover over a background GUI component, even if that background component, (be that a VBox, a Canvas or whatever), uses the correct cursor itself, the cursor reverts to the system cursor, instead of my custom cursor.
Any help appreciated.
Here is a complete worked example, which exactly produces the problem: the http link to that "blue cursor" was live at the time of posting. But please check if you get a problem reproducing.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.ImageCursor;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class CursorTest extends Application {
#Override
public void start(Stage stage) {
SomeDialog someDialog = new SomeDialog(stage);
GridPane root = new GridPane();
HBox buttonHolder= new HBox();
buttonHolder.setPrefSize(300,300);
Scene theScene = new Scene(root);
Canvas canvas = new Canvas();
canvas.setWidth(300);
canvas.setHeight(300);
canvas.getGraphicsContext2D().setFill(Color.RED);
canvas.getGraphicsContext2D().fillRoundRect(100, 100, 100, 100, 10, 10);
Image cursorImg = new Image("http://www.pngmart.com/files/3/Cursor-Arrow-PNG-Transparent-Image.png");
ImageCursor imageCursor = new ImageCursor(cursorImg);
theScene.setCursor(imageCursor);
stage.setTitle("Ribbon dialog");
stage.setScene(theScene);
VBox vBox = new VBox();
vBox.getChildren().add(canvas);
vBox.setSpacing(50);
Button button = new Button("Show modal");
button.setPadding(new Insets(30,30,30,30));
button.setOnMouseClicked(event -> {
someDialog.showMeAndWait();
});
buttonHolder.getChildren().add(button);
root.getChildren().addAll(vBox, buttonHolder);
stage.show();
}
class SomeDialog {
Stage newStage;
public SomeDialog(Stage primaryStage) {
newStage = new Stage();
GridPane gridPane = new GridPane();
Scene theScene = new Scene(gridPane);
Image cursorImg = new Image("http://www.pngmart.com/files/3/Cursor-Arrow-PNG-Transparent-Image.png");
ImageCursor imageCursor2 = new ImageCursor(cursorImg);
theScene.setCursor(imageCursor2);
theScene.setCursor(imageCursor2);
theScene.setFill(Color.TRANSPARENT);
newStage.initOwner(primaryStage);
newStage.initModality(Modality.APPLICATION_MODAL);
newStage.setTitle("Player inventory");
newStage.setScene(theScene);
newStage.initStyle(StageStyle.TRANSPARENT);
VBox vBox = new VBox();
Button someBtn = new Button("Close");
someBtn.setPadding(new Insets(100,100,100,100));
someBtn.setOnMouseClicked(event -> newStage.close());
vBox.getChildren().add(someBtn);
gridPane.getChildren().add(vBox);
}
public void showMeAndWait() {
newStage.showAndWait();
}
}
}

JavaFx Multiple Layouts

I'm currently trying to create this Layout.
I've tried to use:
StackPane rootPane = new StackPane();
Scene scene = new Scene(rootPane,...);
Pane pane1 = new Pane();
Pane pane2 = new Pane();
rootPane.getChildren().addAll(pane1,pane2);
To let me create a menubar as well as a text field directly underneath it but it does not let me as the text field gets hidden by the menuBar.
I'm not sure which ones are needed in my case. I had a look at vbox - this is similar to what i what I need but I'm unsure how to add 2 tables in the last row with a gap
Would be a great help if you could point me in the direction needed.
StackPane is not a good choice here: it simply stacks child nodes on top of each other in z-order. I recommend you read the tutorial on layouts to get a full description of all the built-in layout panes, but one option is to use a VBox. To place the items in the bottom row, you could use an AnchorPane with one item anchored to the left and one to the right.
Here's an SSCCE using this approach:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.TextArea;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class LayoutExample extends Application {
#Override
public void start(Stage primaryStage) {
VBox root = new VBox(5);
root.setPadding(new Insets(5));
MenuBar menuBar = new MenuBar();
menuBar.getMenus().add(new Menu("File"));
TextArea textArea = new TextArea();
VBox.setVgrow(textArea, Priority.ALWAYS);
AnchorPane bottomRow = new AnchorPane();
Label table1 = new Label("Table 1");
table1.setStyle("-fx-background-color: gray");
table1.setMinSize(200, 200);
Label table2 = new Label("Table 2");
table2.setStyle("-fx-background-color: gray");
table2.setMinSize(200, 200);
AnchorPane.setLeftAnchor(table1, 0.0);
AnchorPane.setRightAnchor(table2, 0.0);
bottomRow.getChildren().addAll(table1, table2);
root.getChildren().addAll(menuBar, textArea, bottomRow);
Scene scene = new Scene(root, 800, 800);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Another, similar, approach would be to use a BorderPane as the root, with the menu bar in the top, text area in the center, and anchor pane in the bottom.

Add text under buttons in Dialog

I was wondering if there is a way to display some text (like a info) under the buttons of a Dialog ? I've looked in many places, but even to align the buttons seems messy (from this post).
This is what I got for now. I just want the "Set my choice ..." text under the 2 buttons.
I looked for a function in the documentation that could help me display the way I want (like "getButtonBar()" or something like that) with no chance. Also creating a new ButtonBar seems a bit complicated for what I want to achieve.
I also tried to create a stage that could look like a dialog, but I needed the result incoming from clicking "Yes / No" in the same way the Dialogs do.
Is there any way to achieve want I want ? Or do I have to build it completely myself ? Thanks !
Just override the createButtonBar() method of DialogPane:
DialogPane pane = new DialogPane() {
#Override
public Node createButtonBar() {
VBox vbox = new VBox(5);
vbox.setAlignment(Pos.BOTTOM_RIGHT);
vbox.setPadding(new Insets(5));
vbox.getChildren().add(super.createButtonBar());
vbox.getChildren().add(new Label("Additional text"));
return vbox ;
}
};
Here's a SSCCE:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Dialog;
import javafx.scene.control.DialogPane;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CustomDialogPaneTest extends Application {
#Override
public void start(Stage primaryStage) {
Button button = new Button("Show Dialog");
button.setOnAction(e -> {
DialogPane pane = new DialogPane() {
#Override
public Node createButtonBar() {
VBox vbox = new VBox(5);
vbox.setAlignment(Pos.BOTTOM_RIGHT);
vbox.setPadding(new Insets(5));
vbox.getChildren().add(super.createButtonBar());
vbox.getChildren().add(new Label("Additional text"));
return vbox ;
}
};
CheckBox checkBox = new CheckBox("A check box");
pane.setContent(checkBox);
pane.setHeaderText("The header");
pane.getButtonTypes().addAll(ButtonType.YES, ButtonType.NO);
Dialog<ButtonType> dialog = new Dialog<>();
dialog.setDialogPane(pane);
dialog.showAndWait().ifPresent(System.out::println);
});
StackPane root = new StackPane(button);
root.setPadding(new Insets(20));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Resources