I have integrated a JFileChooser into a JavaFX application using a SwingNode. The dialog displays and is usable, but I am unsure about how to get the selected file from it.
Thanks for any help.
#FXML
public void openDialog(MouseEvent event) {
SwingNode swingNode = new SwingNode();
SwingUtilities.invokeLater(() -> {
swingNode.setContent(fileChooser);
});
BorderPane pane = new BorderPane();
pane.setCenter(swingNode);
Stage stage = new Stage();
Scene scene = new Scene(pane, 500, 500);
stage.setScene(scene);
stage.show();
}
Out of curiosity I made a small example to do this.
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.embed.swing.SwingNode;
import javax.swing.JFileChooser;
import javax.swing.SwingUtilities;
public class JunkFx extends Application {
public void openDialog(MouseEvent event) {
JFileChooser fileChooser = new JFileChooser("why");
SwingNode swingNode = new SwingNode();
SwingUtilities.invokeLater(() -> {
swingNode.setContent(fileChooser);
});
BorderPane pane = new BorderPane();
pane.setCenter(swingNode);
Stage stage = new Stage();
Scene scene = new Scene(pane, 500, 500);
stage.setScene(scene);
stage.show();
fileChooser.addActionListener(evt->{
System.out.println(evt.getActionCommand());
System.out.println(fileChooser.getSelectedFile());
Platform.runLater(stage::hide);
});
}
#Override
public void start(Stage stage) throws Exception {
Button b = new Button("click");
b.setOnMouseClicked(this::openDialog);
Scene scene = new Scene(new StackPane(b), 640, 480);
stage.setTitle("open a dialog");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args){
launch(args);
}
}
There will be a response on the EDT, then you have to manage what to do with it, checking for cancelled or accepted etc. then fire an action onto the Platform thread.
Related
I made a javafx program using a horizontal SplitPane with a Canvas on one side in which something is drawn. When the SplitPane is resized the Canvas resizes with it.
Everything worked fine until I switched to Java 10. Suddenly the Canvas-side can only be expanded, not reduced.
Anyone has an idea why that is?
(The working Java version was 1.8.0_181)
package test;
import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Test extends Application {
private static Display display;
#Override
public void start(Stage primaryStage) {
display = new Display();
StackPane stackPaneDisplay = new StackPane();
stackPaneDisplay.getChildren().add(display);
stackPaneDisplay.setStyle("-fx-background-color: white");
AnchorPane anchorPaneDisplay = new AnchorPane();
anchorPaneDisplay.getChildren().add(stackPaneDisplay);
AnchorPane.setBottomAnchor(stackPaneDisplay, Double.MIN_VALUE);
AnchorPane.setTopAnchor(stackPaneDisplay, Double.MIN_VALUE);
AnchorPane.setLeftAnchor(stackPaneDisplay, Double.MIN_VALUE);
AnchorPane.setRightAnchor(stackPaneDisplay, Double.MIN_VALUE);
display.widthProperty().bind(stackPaneDisplay.widthProperty());
display.heightProperty().bind(stackPaneDisplay.heightProperty());
StackPane stackPaneLeft = new StackPane();
SplitPane splitPane = new SplitPane();
splitPane.setOrientation(Orientation.HORIZONTAL);
splitPane.getItems().addAll(stackPaneLeft, anchorPaneDisplay);
BorderPane root = new BorderPane();
root.setCenter(splitPane);
Scene scene = new Scene(root);
primaryStage.setMaximized(true);
primaryStage.setScene(scene);
primaryStage.show();
splitPane.setDividerPositions(0.2);
}
public static void main(String[] args) {
launch(args);
}
}
and the Canvas-Class
package test;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
public class Display extends Canvas {
GraphicsContext gc = this.getGraphicsContext2D();
public Display() {
widthProperty().addListener(e -> {
draw();
});
}
public void draw() {
gc.strokeOval(500, 500, 100, 100);
}
}
Thanks in advance
Is there any way to prevent new stages from stealing focus from main stage?
I mean each new stage.show(); steals focus from my main stage.
I don't want to mix my JavaFX with Swing, so there's no option for embedding content into JFrame.
Also, it would be great to not use any Popup, just pure Stage.
Is there any external library that allows me to do so?
You can add a listener to the focusedProperty of your primary stage and request focus whenever it loses focus.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class StageFocus extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
final Button button = new Button("New Stage");
button.setOnAction(e -> {
final Stage stage = new Stage();
stage.setWidth(200);
stage.setHeight(200);
stage.setTitle("New Stage");
stage.show();
});
final Scene scene = new Scene(new StackPane(button), 300, 300);
primaryStage.focusedProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue) {
primaryStage.requestFocus();
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
}
I have a stage that acts as popup,I want to close the stage if the user clicks outside that stage,how to achieve that,My code for the stage acting as popup is as follows:
Stage stage = new Stage();
Parent root = FXMLLoader.load(getClass().getResource("colorchange.fxml"));
Scene sce = new Scene(root,400,400);
stage.initModality(Modality.APPLICATION_MODAL);
stage.initOwner(color.getScene().getWindow());
stage.setScene(sce);
stage.showAndWait();
Register a listener with stage.focusedProperty() and call stage.hide() if the focused property changes to false.
SSCCE:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class CloseWindowOnClickOutside extends Application {
#Override
public void start(Stage primaryStage) {
Button showPopup = new Button("Show popup");
showPopup.setOnAction(e -> {
Stage popup = new Stage();
Scene scene = new Scene(new Label("Popup"), 120, 40);
popup.setScene(scene);
popup.initModality(Modality.APPLICATION_MODAL);
popup.initOwner(primaryStage);
popup.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (! isNowFocused) {
popup.hide();
}
});
popup.show();
});
StackPane root = new StackPane(showPopup);
Scene scene = new Scene(root, 350, 120);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Okay so this is the code I used. Most of it comes from the JavaFX tutorial here.
I wanted my program to load a picture when I clicked the button. But it will do the prints but it will not load the picture.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.image.*;;
public class Browser extends Application {
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Test");
Image ph1 = new Image("ph1.jpg");
ImageView disp1 = new ImageView();
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Test1");
disp1.setImage(ph1);
System.out.println("Test2");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Test");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
You haven't added the disp1 ImageView to the root StackPane.
Try this:
StackPane root = new StackPane();
root.getChildren().add(btn);
root.getChildren().add(disp1);
I'm extremely new to JavaFX, and I'm attempting to get a button(specifically scrapeBtn) into the bottom right corner of an application. Here is what I have so far:
package main;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Driver extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Button scrapeBtn = new Button();
scrapeBtn.setText("Scrape!");
scrapeBtn.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
System.out.println("Scrape button pressed.");
}
});
TextField console = new TextField();
GridPane root = new GridPane();
GridPane.setConstraints(scrapeBtn, 2, 2, 1, 1);
root.getChildren().add(scrapeBtn);
root.getChildren().add(console);
Scene scene = new Scene(root, 600, 400);
primaryStage.setTitle("Wiki Scraper");
primaryStage.setScene(scene);
primaryStage.show();
}
}
Any ideas as to how I could accomplish this? Some tips in general to aligning and formatting things with JavaFX would also be really appreciated.
Thanks.
I often use a BorderPane for similar purposes (e.g. a Dialog with some text and controls etc. at the center and one or more buttons at the bottom). Therefore, I use the BorderPane as root and a HBox as "button container" at the bottom. Finally, I set the botton alignment to "RIGHT".
Here an example based on your code:
#Override
public void start(Stage primaryStage) {
// center
VBox vbCenter = new VBox(); // use any container as center pane e.g. VBox
TextField console = new TextField();
vbCenter.getChildren().add(console);
// bottom respectively "button area"
HBox hbButtons = new HBox();
Button scrapeBtn = new Button();
scrapeBtn.setText("Scrape!");
scrapeBtn.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
System.out.println("Scrape button pressed.");
}
});
hbButtons.getChildren().add(scrapeBtn);
hbButtons.setAlignment(Pos.CENTER_RIGHT);
// root
BorderPane root = new BorderPane();
root.setPadding(new Insets(20)); // space between elements and window border
root.setCenter(vbCenter);
root.setBottom(hbButtons);
Scene scene = new Scene(root, 600, 400);
primaryStage.setTitle("Wiki Scraper");
primaryStage.setScene(scene);
primaryStage.show();
}
This code leads to this (after resizing the window a little bit):
You can use two BorderPanes to place a control bottom right
#Override
public void start(Stage primaryStage) throws Exception {
BorderPane root = new BorderPane();
BorderPane bottom = new BorderPane();
bottom.setRight(new Button("I am placed bottom right"));
root.setBottom(bottom);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setWidth(400);
primaryStage.setHeight(400);
primaryStage.show();
}