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.
Related
I have question about blocking Dialog window when I'm opening FileChooser. When I open FileChooser from main app window I don't have any problem with blocking main window of app (using fileChooser.showOpenDialog(Main.getPrimaryStage);). But I have problem when I'm opening Filechooser from Dialog. I can't focus on main app window, because Dialog has property dialog.initOwner(Main.getPrimaryStage());, but I still can focus on Dialog and open next FileChooser, over and over again. App image view. What can I do with this ?
You can get a reference to the window used to display a dialog from its dialogPane, via:
Window dialogWindow = dialog.getDialogPane().getScene().getWindow();
Using this, you can make the "owner" of the file chooser the dialog's window:
Window dialogWindow = dialog.getDialogPane().getScene().getWindow();
File file = fileChooser.showOpenDialog(dialogWindow);
Here's a SSCCE:
import java.io.File;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.DialogPane;
import javafx.scene.layout.StackPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.Window;
public class DialogFileChooser extends Application {
#Override
public void start(Stage primaryStage) {
Button button = new Button("Open Dialog...");
button.setOnAction(e -> createDialog(primaryStage).show());
StackPane root = new StackPane(button);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
private Dialog<ButtonType> createDialog(Window owner) {
DialogPane dialogPane = new DialogPane();
dialogPane.getButtonTypes().add(ButtonType.CLOSE);
Dialog<ButtonType> dialog = new Dialog<>();
dialog.setDialogPane(dialogPane);
Button openFile = new Button("Open File...");
FileChooser fileChooser = new FileChooser();
openFile.setOnAction(e -> {
Window dialogWindow = dialog.getDialogPane().getScene().getWindow();
File file = fileChooser.showOpenDialog(dialogWindow);
System.out.println(file);
});
dialogPane.setContent(new StackPane(openFile));
dialog.initOwner(owner);
return dialog ;
}
public static void main(String[] args) {
launch(args);
}
}
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();
}
}
I'm french, sorry for mistake.
I have an primary stage, and foreground an small second stage. I want to color in gray all the primary stage when the second stage is visible.
It's good, i cannot click in the primary stage with the line :
stage.initModality(Modality.WINDOW_MODAL);
But I want to put a color gray in the primary stage.
I try to disable all componant in the primary stage (every componant is gray and disable) but imageViews are not gray, it's a problem.
Help please.
Thanks.
You can add all to a Stackpane and make a Region as a veil (visible=true/false).
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class VeilDemo extends Application {
#Override
public void start(Stage primaryStage) {
// that is the veil
Region veil = new Region();
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.3)");
veil.setVisible(false);
Button btn = new Button();
btn.setText("Open Dialog");
btn.setOnAction((ActionEvent event) -> {
Alert a = new Alert(Alert.AlertType.INFORMATION);
//veil is only visible when alert window is showing
veil.visibleProperty().bind(a.showingProperty());
a.setContentText("The main window should be decorated with a veil.");
a.setX(primaryStage.getX() + 200); // This is only for showing main window
a.showAndWait();
});
Image img = new Image("https://www.gnu.org/graphics/gnu-head-sm.png");
ImageView iv = new ImageView(img);
// this should be the normal root of window
BorderPane bp = new BorderPane(iv);
bp.setBottom(btn);
StackPane root = new StackPane();
root.getChildren().addAll(bp, veil);
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);
}
}
The main window will look like this:
and if the button was clicked, the info window opens and the veil is visibile on the main stage.
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);
}
}
I want to set Label to graphic. I tested this code:
private static final ImageView livePerformIcon;
static
{
livePerformIcon = new ImageView(MainApp.class.getResource("/images/Flex.jpg").toExternalForm());
}
final Label label = new Label();
label.setStyle("-fx-background-image: url(\"/images/Flex.jpg\");");
livePerformIcon.setFitHeight(20);
livePerformIcon.setFitWidth(20);
label.setGraphic(livePerformIcon);
But I don't see any image.
The only way that I found to make it work is this:
label.setStyle("-fx-background-image: url(\"/images/Flex.jpg\");");
Is there a way to solve this?
Not sure, but AFAIK controls should be created on the JavaFX Application thread, but you're creating ImageView in a static initializer, which I'm not sure if it's executed on the Application thread.
Besides: Do you really want livePerformIcon to be static???
This one made from the data used in the docs, works perfectly for me
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class LabelWithImages extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Label With Image Sample");
stage.setWidth(400);
stage.setHeight(180);
HBox hbox = new HBox();
//Replace the image you want to put up
Image image = new Image(getClass().getResourceAsStream("a.png"));
Label label = new Label("Demo Label");
label.setGraphic(new ImageView(image));
hbox.setSpacing(10);
hbox.getChildren().add((label));
((Group) scene.getRoot()).getChildren().add(hbox);
stage.setScene(scene);
stage.show();
}
}
Code snippets below will set the value of the property graphic of a label. You can use any of the two. I prefer using javafx css, just to implement the model-view-controller design.
// programmatically, provided with image input stream
label.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("path/to/image.png"))));
// javafx css, provided with image url
.label {
-fx-graphic: url("path/to/image.png");
}