JavaFX custom dialog set Layout of node - javafx

We created a Custom Dialog without an FXML file. We are using JavaFX 8.
The dialog loads and functions as expected but we can not move the Buttons and the TextField to enhance the styling.
We have tried to use tf.setLayoutY(50) this has no effect.
We used this tf.setPromptText("This Works ?") and it works.
We would rather not use css to accomplish this styling.
And we will consider a FXML file if we can keep the two event handlers that force data to be entered in the TextField.
So the question is: How to style this Custom Dialog?
The code is a mess as it includes some concepts we tried:
public void CustomDialog() {
Dialog dialog = new Dialog<>();
dialog.setResizable(false);
final Window window = dialog.getDialogPane().getScene().getWindow();
stage = (Stage) window;
stage.setMinHeight(600);
stage.setMinWidth(400);
TextField tf = new TextField();
tf.setLayoutX(10);
tf.setLayoutY(50);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
dialog.getDialogPane().getChildren().add(tf);
dialog.getDialogPane().setContent(tf);
// Create an event filter that consumes the action if the text is empty
EventHandler<ActionEvent> filter = event -> {
if (tf.getText().isEmpty()) {
event.consume();
}
};
// lookup the buttons
ButtonBase okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
Button cancelButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.CANCEL);
// add the event-filter
okButton.addEventFilter(ActionEvent.ACTION, filter);
cancelButton.addEventFilter(ActionEvent.ACTION, filter);
stage.setOnCloseRequest(event -> {
if (tf.getText().isEmpty()) {
event.consume();
}
}
//Scene scene = new Scene(root);
//dialogStage.setScene(scene);
dialog.initModality(Modality.APPLICATION_MODAL);
//dialogStage.setAlwaysOnTop(true);
//dialogStage.setResizable(false);
tf.setPromptText("This Works ?");
tf.requestFocus();// This does not work
dialog.showAndWait();
}

Grendel we enhanced your answer so anyone who comes by and sees the code you posted in your question will understand as you said it was a mess
Your posted answer was real old school but less work perhaps than building a FXML file
Besides it is good to know some old school tricks
public void NewDialog(){
Label lblAmt = new Label("Enter Amount");
Button btnOK = new Button("OK");
TextField txtAmt = new TextField();
AnchorPane secondaryLayout = new AnchorPane();
secondaryLayout.setStyle("-fx-border-color:red;-fx-border-width:10px; -fx-background-color: lightblue;");
secondaryLayout.getChildren().addAll(lblAmt,btnOK,txtAmt);
lblAmt.setLayoutX(30);
lblAmt.setLayoutY(30);
txtAmt.setLayoutX(164);
txtAmt.setLayoutY(25);
txtAmt.setMaxWidth(116);
btnOK.setLayoutX(190);
btnOK.setLayoutY(100);
btnOK.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
lblAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
txtAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
Scene secondScene = new Scene(secondaryLayout, 300, 180);
EventHandler<ActionEvent> filter = event -> {
if(txtAmt.getText().isEmpty()) {
event.consume();
}
};
// New window (Stage)
Stage newWindow = new Stage();
newWindow.initStyle(StageStyle.UNDECORATED);
//newWindow.initModality(Modality.APPLICATION_MODAL);
newWindow.setResizable(false);
newWindow.setTitle("Second Stage");
newWindow.setScene(secondScene);
btnOK.addEventHandler(ActionEvent.ACTION,filter);
btnOK.setOnAction(evt -> {
String str = txtAmt.getText();
System.out.println("################ str "+str);
if(txtAmt.getText().equals("")) {
evt.consume();
txtAmt.requestFocus();
}else{
newWindow.close();
}
});
newWindow.setOnCloseRequest(event -> {
if(txtAmt.getText().isEmpty()) {
event.consume();
}
});
txtAmt.requestFocus();
newWindow.showAndWait();
}

Related

Can you set icon to a Javafx Alert box? [duplicate]

I might be missing something very obvious, but I can't find out how to set the Icon for a Dialog component (ProgressDialog to be more precise). I know how to do that for a Stage:
this.primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/icon/Logo.png")));
But I don't find anything for the Dialog family. And somehow, setting the Stage Icon does not influence the Dialog Icon.
Thanks
There's an excellent tutorial here by Marco Jakob, where you can find not only how to use dialogs, but also how to solve your problem.
Both for the new dialogs (in JDK8u40 early versions or with openjfx-dialogs with JDK 8u25), or for those in ControlsFX, in order to set the icon of your dialog, you can use this solution:
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
stage.getIcons().add(
new Image(this.getClass().getResource("<image>.png").toString()));
This code snippet shows how to use a ProgressDialog, from ControlsFX, and set an icon for the dialog:
#Override
public void start(Stage primaryStage) {
Service<Void> service = new Service<Void>() {
#Override protected Task<Void> createTask() {
return new Task<Void>() {
#Override protected Void call() throws InterruptedException {
updateMessage("Message . . .");
updateProgress(0, 10);
for (int i = 0; i < 10; i++) {
Thread.sleep(300);
updateProgress(i + 1, 10);
updateMessage("Progress " + (i + 1) + " of 10");
}
updateMessage("End task");
return null;
}
};
}
};
Button btn = new Button("Start Service");
btn.setOnAction(e -> {
ProgressDialog dialog = new ProgressDialog(service);
dialog.setTitle("Progress Dialog");
dialog.setHeaderText("Header message");
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
stage.getIcons().add(new Image(this.getClass().getResource("<image>.png").toString()));
service.start();
});
Scene scene = new Scene(new StackPane(btn), 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
Just Do like this:
Alert(AlertType.ERROR, "Erreur de connexion! Verifiez vos Identifiants",FINISH); //Cancel..
setTitle("XNotes FX Erreur");
stage = (Stage) alert.getDialogPane().getScene().getWindow();
stage.getIcons().add(new Image("indiza/XnotesErrorIdz.png")); // To add an icon
showAndWait();
Here is the result
**My friends, is it computer science that we do? : No, we do crafts
**
You can easily use the icon of your application for the alert-icon by setting your application-window as owner of the alert box:
#FXML
Button buShow;
...
Alert alert = new Alert(AlertType.INFORMATION, "Nice Box.", ButtonType.CLOSE);
alert.initOwner(buShow.getScene().getWindow()); // Alert uses the Windows Icon
alert.show();
This is a method that I include in my JavaFX projects, simply calling this method and passing the Alert as a parameter will set both the title bar icon and the header graphic.
public class Msg {
public void showInfo(String title, String header, String message) {
Alert alertShowInfo = new Alert(Alert.AlertType.INFORMATION);
addDialogIconTo(alertShowInfo); //add icon and header graphic
alertShowInfo.setTitle(title);
alertShowInfo.setHeaderText(header);
alertShowInfo.setContentText(message);
alertShowInfo.showAndWait();
}
//this adds images to Alert
public void addDialogIconTo(Alert alert) {
// Add custom Image to Dialog's title bar
final Image APPLICATION_ICON = new Image("icon.png");
Stage dialogStage = (Stage) alert.getDialogPane().getScene().getWindow();
dialogStage.getIcons().add(APPLICATION_ICON);
// Add custom ImageView to Dialog's header pane.
final ImageView DIALOG_HEADER_ICON = new ImageView("icon.png");
DIALOG_HEADER_ICON.setFitHeight(48); // Set size to API recommendation.
DIALOG_HEADER_ICON.setFitWidth(48);
alert.getDialogPane().setGraphic(DIALOG_HEADER_ICON);
}
}
Then, in whatever class I wish to use the Alert, it will already have the customized icon and header graphic.
public static void main(String[] args){
Msg msg = new Msg();
// Alert will now include custom icon and header graphic.
msg.showInfo("Sucess!", "Program succeeded", "Now exiting program");
}
Just similar to any dialog, instead this is inside a button handler.
Alert alert = new Alert(
AlertType.WARNING,
"Alert message here.",
ButtonType.OK
);
alert.initOwner(((Button)event.getSource()).getScene().getWindow());
alert.setTitle("Alert window title");
alert.showAndWait();

Key Listener in JavaFX that changes on button press

My controller class has a moveButton method that on button click moves the button to a new location. This works fine and is called by a number of buttons which do the same thing. I want to add a key listener so when a button has been clicked once, until a different button is clicked, the user can use the up arrow to move the button (ie call the same moveButton function). The below is how I have tried to implement it, I also tried putting the key listener in the initialize method but neither seem to be working. Any advice would be greatly appreciated!
public void moveButton(ActionEvent actionEvent) {
Button buttonPressed = (Button) actionEvent.getSource();
double newAnchor = getNewAnchor(AnchorPane.getBottomAnchor(buttonPressed)) // separate method that returns new anchor location
AnchorPane.setBottomAnchor(buttonPressed, newAnchor);
buttonPressed.getScene().setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.UP){
moveButton(actionEvent);
}
}
});
}
Don't treat the events like data that you need to pass around. Use them as triggers to do work. Generally, don't write generic event handlers that are called from multiple events and multiple nodes. Write short event handlers that just call methods to do something, and pass them the minimum from the event that they need to do the job.
If you do this, then it changes your thinking about how all of this stuff works and then it's just plain old Java, with no magic. And it's simple:
public class MoveButton extends Application {
private Node activeButton;
private Pane pane;
#Override
public void start(Stage primaryStage) throws Exception {
pane = new Pane();
Scene scene = new Scene(pane, 1200, 800);
primaryStage.setScene(scene);
primaryStage.show();
Button button1 = new Button("Button 1");
Button button2 = new Button("Button 2");
button2.setTranslateX(80);
button1.setOnAction(evt -> buttonClick(button1));
button2.setOnAction(evt -> buttonClick(button2));
pane.getChildren().addAll(button1, button2);
pane.setOnKeyPressed(evt -> moveButton(evt.getCode()));
}
private void moveButton(KeyCode keyCode) {
switch (keyCode) {
case UP -> activeButton.setTranslateY(activeButton.getTranslateY() - 30);
case RIGHT -> activeButton.setTranslateX(activeButton.getTranslateX() + 30);
case DOWN -> activeButton.setTranslateY(activeButton.getTranslateY() + 30);
case LEFT -> activeButton.setTranslateX(activeButton.getTranslateX() - 30);
}
}
private void buttonClick(Node button) {
activeButton = button;
pane.requestFocus();
}
}

How to set the scrollPane to the desired vValue?

I have a tilepane inside a scrollpane. The tilepane is filled with buttons that have actions like delete or edit. After I delete or edit a button, the scrollpane automatically goes back to the top, which I don't want. I want it to remain at the current position (the position the user scrolled to).
I tried getting and setting the vValue of the scrollpane. getvValue gets the value and the setter sets it, but the scrollpane doesn't respond to it and goes back to the top after the action (delete/ edit). I tried a solution from this question: JavaFX ScrollPane setVvalue() not working as intended, but the layout() method doesn't do anything either. What am I doing wrong here? How do I make the scrollpane stay where it is?
EDIT: I found the problem, but still don't know how to fix it. Apparently setting and changing the visibility on the hBoxes in fxml puts the scrollpane back to the top. If I remove the setVisible methods and run it, I can delete items and the scrollpane stays in position. How to fix this?
On request I created a Minimal, Complete, and Verifiable example of my code. Run it, scroll down a bit, right click a button with a name and price on it and then click delete. It scrolls back up to the top.
This is my code:
public class Controller {
private static LinkedHashMap<String, BigDecimal> mProductMap = new LinkedHashMap<>();
#FXML private TilePane fieldContainer = new TilePane();
#FXML private ScrollPane scroll;
#FXML private Button deletebtn;
#FXML private Button editbtn;
#FXML private HBox homeBar;
#FXML private HBox actionBar;
#FXML
private void initialize() {
addProduct("Coffee", new BigDecimal("2.00"));
addProduct("Tea", new BigDecimal("2.00"));
addProduct("Cappuccino", new BigDecimal("2.00"));
addProduct("Espresso", new BigDecimal("2.00"));
addProduct("Cooky", new BigDecimal("2.00"));
addProduct("Candy", new BigDecimal("2.00"));
addProduct("Chocobar", new BigDecimal("2.00"));
addProduct("Cola", new BigDecimal("2.00"));
addProduct("Fanta", new BigDecimal("2.00"));
addProduct("Beer", new BigDecimal("2.00"));
addProduct("Salad", new BigDecimal("2.00"));
addProduct("Sandwich", new BigDecimal("2.00"));
addProduct("Water", new BigDecimal("2.00"));
addProduct("Cassis", new BigDecimal("2.00"));
}
// makes the delete and edit buttons appear after selecting a button from the tilepane
private void select(String selectedProduct) {
/*
the setVisible method for the hBoxes in fxml cause the scrollbar to go back to the top
without them, the scrollpane stays where it is.
I tried changing visibility with both setVisible and CSS, but they both cause the problem
I need the actionbar to appear when you select a button (right click on it)
*/
homeBar.setVisible(false);
actionBar.setVisible(true);
EventHandler<ActionEvent> delete = event -> {
deleteProduct(selectedProduct); // deletes an item from a LinkedHashMap
homeBar.setVisible(true);
actionBar.setVisible(false);
};
deletebtn.setOnAction(delete);
// I want the same to happen when the edit handler is used, scrollpane needs to remain its position
EventHandler<ActionEvent> edit = event -> {
editProduct(selectedProduct); // edits an item from a LinkedHashMap
homeBar.setVisible(true);
actionBar.setVisible(false);
};
editbtn.setOnAction(edit);
}
/*
Code below does not cause the problem, but I added it as a reference
*/
private void deleteProduct(String product) {
if (mProductMap.containsKey(product)) {
mProductMap.remove(product);
System.out.printf("%s has been deleted!%n", product);
} else {
System.out.printf("%s does not exist. Please try again.%n", product);
}
addButtons();
}
private void editProduct(String product) {
List<String> indexKeys = new ArrayList<>(mProductMap.keySet());
List<BigDecimal> indexValues = new ArrayList<>(mProductMap.values());
BigDecimal price = mProductMap.get(product); // gets the product's value (the price)
int indexKey = indexKeys.indexOf(product);
int indexValue = indexValues.indexOf(price);
if (mProductMap.containsKey(product)) {
int sizeBefore = mProductMap.size();
addingProduct();
int sizeAfter = mProductMap.size();
if (sizeAfter > sizeBefore) {
indexKeys.remove(product);
indexValues.remove(price);
mProductMap.remove(product);
// Make a new list to get the new entry at the end
List<Map.Entry<String,BigDecimal>> entryList = new ArrayList<>(mProductMap.entrySet());
Map.Entry<String, BigDecimal> lastEntry = entryList.get(entryList.size()-1);
String key = lastEntry.getKey();
BigDecimal value = lastEntry.getValue();
indexKeys.add(indexKey, key);
indexValues.add(indexValue, value);
mProductMap.clear();
// Put the keys and values from the two lists back to the map
for (int i=0; i<indexKeys.size(); i++) {
addProduct(indexKeys.get(i), indexValues.get(i));
}
}
} else {
System.out.printf("%s does not exist. Please try again.%n", product);
}
}
void addProduct(String product, BigDecimal price) {
mProductMap.put(product, price);
addButtons();
}
// Adding buttons to the TilePane fieldContainer in center of BorderPane
// One button per key-value pair of mProductMap
private void addButtons() {
// clears the TilePane to prevent duplicate buttons
fieldContainer.getChildren().clear();
for (Map.Entry<String, BigDecimal> entry : mProductMap.entrySet()) {
StackPane newField = new StackPane();
Button main = new Button();
main.setOnMousePressed(me -> {
if (me.getButton() == MouseButton.SECONDARY) { // = right click
select(entry.getKey());
}
});
main.setText(entry.getKey() + "\n" + entry.getValue());
newField.getChildren().add(main);
fieldContainer.setAlignment(Pos.TOP_LEFT);
fieldContainer.getChildren().add(newField);
}
}
// Popup for adding products to the Map with the + button
#FXML
private void addingProduct(){
Stage newStage = new Stage();
VBox popup = new VBox();
final BooleanProperty firstTime = new SimpleBooleanProperty(true); // Variable to store the focus on stage load
TextField product = new TextField("");
product.setId("product");
product.setPromptText("Enter the item name...");
// code to remove the focus from first textfield on stage load
product.focusedProperty().addListener((observable, oldValue, newValue) -> {
if(newValue && firstTime.get()){
popup.requestFocus(); // Delegate the focus to container
firstTime.setValue(false); // Variable value changed for future references
}
});
TextField price = new TextField("");
price.setId("price");
price.setPromptText("Enter the item price...");
Button submit = new Button("Submit");
Label label = new Label();
label.setId("label");
submit.setOnAction(e -> {
if ( (product.getText() != null && !product.getText().isEmpty() &&
price.getText() != null && !price.getText().isEmpty() ) ) {
addProduct(product.getText(), new BigDecimal(price.getText()) );
newStage.close();
} else {
label.setText("Fill in both fields");
}
});
popup.getChildren().add(product);
popup.getChildren().add(price);
popup.getChildren().add(submit);
popup.getChildren().add(label);
Scene stageScene = new Scene(popup, 300, 200);
newStage.setScene(stageScene);
newStage.showAndWait();
}
}
The FXML:
<BorderPane xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<top>
<StackPane>
<HBox fx:id="homeBar" styleClass="main-bar" visible="true">
<Button StackPane.alignment="BOTTOM_LEFT">Home</Button>
<Button onAction="#addingProduct" StackPane.alignment="BOTTOM_RIGHT">Add a new product</Button>
</HBox>
<HBox fx:id="actionBar" styleClass="main-bar" visible="false">
<Button fx:id="deletebtn" StackPane.alignment="BOTTOM_CENTER">Delete</Button>
<Button fx:id="editbtn" StackPane.alignment="BOTTOM_CENTER">Edit</Button>
<Button onAction="#addingProduct" StackPane.alignment="BOTTOM_RIGHT">Add a new product</Button>
</HBox>
</StackPane>
</top>
<center>
<ScrollPane fx:id="scroll" hbarPolicy="NEVER">
<TilePane fx:id="fieldContainer" prefColumns="2" prefTileHeight="100.0" prefTileWidth="144.0">
</TilePane>
</ScrollPane>
</center>
<bottom>
</bottom>
</BorderPane>
Main:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I fixed it myself, with help from answers from this post: ScrollPane jumps to top when deleting nodes.
After deleting a button from the TilePane, the ScrollPane finds the next node to focus on, which by default is the first node from the pane. By requesting the focus on the TilePane (fieldContainer) the ScrollPane stays in place.
I added this code to both the delete and edit methods:
fieldContainer.requestFocus();

JavaFX ScrollPane PannableProperty with TitledPane

I'm building a GUI application with javafx that needs PannableProperty from the ScrollPane to work when the user drag the content of it from anywhere.
In oracle docs they say about the "pannableProperty":
Specifies whether the user should be able to pan the viewport by using
the mouse. If mouse events reach the ScrollPane (that is, if mouse
events are not blocked by the contained node or one of its children)
then pannable is consulted to determine if the events should be used
for panning.
So my problem is the mouse event cannot reach the ScrollPane..
Anyone has a clue how to make it possible?
this is a simple code to test it:
ScrollPane root = new ScrollPane();
root.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
root.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
root.setPannable(true);
VBox v = new VBox(10);
TitledPane c1 = new TitledPane("test: ", new HBox(new Label("test: "), new TextField()));
HBox c2 = new HBox(new Label("we are just in HBox "), new TextField());
Label c3 = new Label("I'm just a label and pannableProperty works here");
TitledPane c4 = new TitledPane("test4", new HBox(new Label("test: "), new TextField()));
AnchorPane c5 = new AnchorPane();
c5.setPrefSize(100, 100);
v.getChildren().addAll(c1, c2, c3, c4, c5);
root.setContent(v);
Scene scene = new Scene(root, 300, 300);
primaryStage.setScene(scene);
primaryStage.show();
Another tricky one :-)
The default Skin implementation of the TitledPane is a subclass of SkinBase and the default constructor (which gets invoked by TitledPaneSkin) does this (shortened version):
protected SkinBase(final C control) {
// Default behavior for controls is to consume all mouse events
consumeMouseEvents(true);
}
So we need to reverse this, unfortunately you have to do reflection for this:
TitledPane c1 = new TitledPane("test: ", new HBox(new Label("test: "), new TextField()));
c1.skinProperty().addListener((w,o,n)-> {
if(n instanceof SkinBase) {
SkinBase<?> skinbase = (SkinBase<?>) n;
try {
Method m = SkinBase.class.getDeclaredMethod("consumeMouseEvents", Boolean.TYPE);
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
boolean wasAccessible = m.isAccessible();
try {
m.setAccessible(true);
m.invoke(skinbase, false);
return null;
}
catch(ReflectiveOperationException e) { throw new IllegalStateException(e); }
finally {
m.setAccessible(wasAccessible);
}
});
} catch (ReflectiveOperationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
And now it should work, at least it does in my test application.
EDIT #1:
Doing this resets the focus during mouse operations, which renders the TitledPane somewhat unusable. So we are now messing with the focus system:
ScrollPane root = new ScrollPane();
root.setFocusTraversable(false);
Scene scene = new Scene(root, 300, 300);
scene.focusOwnerProperty().addListener((w,o,n)->
if(n == root && o != null) {
o.requestFocus();
}
});
Basically what we are doing here is that we re-focus the previously focussed component if the newly focused element is the ScrollPane.

How to create a modal window in JavaFX 2.1

I can't figure out how to create a modal window in JavaFX. Basically I have file chooser and I want to ask the user a question when they select a file. I need this information in order to parse the file, so the execution needs to wait for the answer.
I've seen this question but I've not been able to find out how to implement this behavior.
In my opinion this is not good solution, because parent window is all time active.
For example if You want open window as modal after click button...
private void clickShow(ActionEvent event) {
Stage stage = new Stage();
Parent root = FXMLLoader.load(
YourClassController.class.getResource("YourClass.fxml"));
stage.setScene(new Scene(root));
stage.setTitle("My modal window");
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(
((Node)event.getSource()).getScene().getWindow() );
stage.show();
}
Now Your new window is REALY modal - parent is block.
also You can use
Modality.APPLICATION_MODAL
Here is link to a solution I created earlier for modal dialogs in JavaFX 2.1
The solution creates a modal stage on top of the current stage and takes action on the dialog results via event handlers for the dialog controls.
JavaFX 8+
The prior linked solution uses a dated event handler approach to take action after a dialog was dismissed. That approach was valid for pre-JavaFX 2.2 implementations. For JavaFX 8+ there is no need for event handers, instead, use the new Stage showAndWait() method. For example:
Stage dialog = new Stage();
// populate dialog with controls.
...
dialog.initOwner(parentStage);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.showAndWait();
// process result of dialog operation.
...
Note that, in order for things to work as expected, it is important to initialize the owner of the Stage and to initialize the modality of the Stage to either WINDOW_MODAL or APPLICATION_MODAL.
There are some high quality standard UI dialogs in JavaFX 8 and ControlsFX, if they fit your requirements, I advise using those rather than developing your own. Those in-built JavaFX Dialog and Alert classes also have initOwner and initModality and showAndWait methods, so that you can set the modality for them as you wish (note that, by default, the in-built dialogs are application modal).
You can create application like my sample. This is only single file JavaFX application.
public class JavaFXApplication1 extends Application {
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Stage stage;
stage = new Stage();
final SwingNode swingNode = new SwingNode();
createSwingContent(swingNode);
StackPane pane = new StackPane();
pane.getChildren().add(swingNode);
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle("Swing in JavaFX");
stage.setScene(new Scene(pane, 250, 150));
stage.show();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
private void createSwingContent(final SwingNode swingNode) {
SwingUtilities.invokeLater(() -> {
try {
Path currentRelativePath = Paths.get("");
String s = currentRelativePath.toAbsolutePath().toString();
JasperDesign jasperDesign = JRXmlLoader.load(s + "/src/reports/report1.jrxml");
String query = "SELECT * FROM `accounttype`";
JRDesignQuery jrquery = new JRDesignQuery();
jrquery.setText(query);
jasperDesign.setQuery(jrquery);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint JasperPrint = JasperFillManager.fillReport(jasperReport, null, c);
//JRViewer viewer = new JRViewer(JasperPrint);
swingNode.setContent(new JRViewer(JasperPrint));
} catch (JRException ex) {
Logger.getLogger(AccountTypeController.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}

Resources