APP JFXOptions for JavaFX Application

Joe

Thành viên VIP
21/1/13
2,958
1,323
113
Hi
SWING has the very useful JOptionPane for the case that an app needs some interactive dialogs beside the Error or Warning or Information pop-up. And I have showed you the customized JOptionPane as JOptions which allows an app to pop up a dialog for:
  1. simple input: JOptions.input()
  2. password: JOptions.password()
  3. multipleInputs with or without defaults: JOptions.multipleInputs()
  4. dynamicInputs: JOptions.dynamicInputs()
Well, what about JavaFX? JavaFX developers certainly know some Dialog APIs such as Alert, TextInputDialog, etc. These dialogs work exactly like the JOptionPane static methods (JOptionPane.showMessageDialog , JOptionPane.showInputDialog, etc.) But life is NOT as convenient as one would like to have. Sometimes you want to have a pop-up dialog for PASSWORD like JOptions.password() or multiple inputs at a time like JOptions.multipleInputs(), etc. if so you have to customize the common JavaFX Dialog as I did with JOptionPane. How? I show you hereunder the JavaFX customized Dialog and name it JFXOptions as the counterpart of JOptions. And JFXOptions works exactly like JOptions:
  1. simple input: JFXOptions.input()
  2. password: JFXOptions.password()
  3. multipleInputs with or without defaults: JOptionsRX.multipleInputs()
  4. dynamicInputs: JFXOptions.dynamicInputs()
Example: JFXOptions.multipleInputs with defaults
Java:
  /**
  multipleInputs with Labels and Defaults. The number of input fields is equal the number of the given lab array
  <br>Click OK to terminate the input process, X-CLOSE to escape.
  @param css customized CSS file name or null for JFX defaults
  @param lab String array for the input labels
  @param obj default object array (element as a string or a string array)
  @param header String
  @return Array of input Strings, null if closed
  */
  public static String[] multipleInputs(String css, String[] lab, Object[] obj, String header) {
    Dialog<ButtonType> dia = new Dialog<ButtonType>();
    //
    dia.setTitle("JFXOptions");
    dia.setHeaderText(header);
    dia.setResizable(true);
    // set the min. width for this dialog
    ((Stage)dia.getDialogPane().getScene().getWindow()).setMinWidth(250);
    // Grid of components
    GridPane grid = new GridPane();
    grid.setHgap(5);
    grid.setVgap(2);
    // Set up dialog pane
    DialogPane diaPane = dia.getDialogPane();
    diaPane.getButtonTypes().addAll(ButtonType.OK);
    diaPane.setContent(grid);
    // load labels and defaults
    boolean focus = false;
    for (int i = 0; i < lab.length; ++i) {
      Label label = new Label(lab[i]);
      grid.add(label, 0, i);
      grid.setHalignment(label, HPos.RIGHT);
      if (obj[i] instanceof String[]) {
        String[] sa = (String[])obj[i];
        ComboBox<String> combo = new ComboBox<>( );
        combo.getItems().addAll(Arrays.asList(sa));
        grid.setHalignment(combo, HPos.LEFT);
        combo.setValue(sa[0]);
        grid.add(combo, 1, i);
      } else { // String or null
        TextField txt = new TextField( );
        if (obj[i] != null) txt.setText((String)obj[i]);
        grid.setHalignment(txt, HPos.LEFT);
        grid.add(txt, 1, i);
        if (!focus) {
          Platform.runLater(() -> txt.requestFocus());
          focus = true;
        }
      }
    }
    if (css != null && (new File(css)).exists()) {
      diaPane.getStylesheets().add(css);
      diaPane.getStyleClass().add("css");
    }
    Optional<ButtonType> B = dia.showAndWait();
    try {
      ButtonType but = B.get();
      if (but == ButtonType.OK) {
        ObservableList<Node> nodes = grid.getChildren();
        List<String> list = new ArrayList<>( );
        for (Node n:nodes) {
          if (n instanceof ComboBox) list.add((String)((ComboBox)n).getValue());        
          else if (n instanceof TextField) list.add(((TextField)n).getText().trim());
        }
        return list.toArray(new String[list.size()]);
      }
    } catch (Exception ex) { }
    return null;
  }
The pop-up dialog is as following:
JFXOptions_multiple.png

The application of JFXOptions methods are similar to those of SWING JOptions and JOptionsTest
Java:
// Java
import java.util.*;
// Java FX
import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.text.*;
import javafx.scene.layout.*;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.geometry.*;
import javafx.event.*;
// Joe Nartca (C)
public class JFXOptionsTest extends Application {
  public void start(Stage stage) {
    stage.setMinWidth(250);
    stage.setTitle("JFXOptions");
    //
    Button pla = new Button("input");
    pla.setOnAction(e -> {
      System.out.println(JFXOptions.input("css.css", "JFXOptions.input"));
    });
    Button pas = new Button("password");
    pas.setOnAction(e -> {
      System.out.println(JFXOptions.password("css.css", "JFXOptions.password"));
    });
    Button dyn = new Button("dynamicInputs");
    dyn.setOnAction(e -> {
      List<String> inp  = JFXOptions.dynamicInputs("css.css", "JFXOptions.dynamicInputs");
      if (inp != null) for (String S:inp) System.out.println(S);
    });
    Button mul_1 = new Button("MultipleInputs");
    mul_1.setOnAction(e -> {
      Object[] objs = { "Joe", "20!21!22!23!24!25!26!27!28!29!30!31!32!33!34!35!36!37!38!39!40!41!42!43!44!45!".split("!"),
                        "male!female".split("!"), null, null, null, null };
      String inp[] = JFXOptions.multipleInputs("css.css",
                                               "Name!Age!Gender!Address!Profession!Country".split("!"),
                                               objs,
                                               "JOptions.multipleInputs");
      if (inp != null) for (String S:inp) System.out.println(S);
    });
    Button mul_2 = new Button("MultipleInputs");
    mul_2.setOnAction(e -> {
      String inp[] = JFXOptions.multipleInputs("css.css",
                                               "Name!Age!Gender!Address!Profession!Country".split("!"),
                                               "JOptions.multipleInputs");
      if (inp != null) for (String S:inp) System.out.println(S);
    });
    // All VBox
    VBox vbox = new VBox(5);
    vbox.setAlignment(Pos.CENTER);
    vbox.setPadding(new Insets(5, 0, 5, 0));
    vbox.getChildren().setAll(pla, pas, dyn, mul_1, mul_2);

    Scene scene = new Scene(vbox);
    stage.setScene(scene);
    stage.show();
  }
  public void stop() {
    Platform.runLater(() -> {
        Platform.exit();
    });
    System.exit(0);
  }
}
The pop-ups with/without CSS (Cascade Style Sheet)

JFXOptions_dynamic.png

JFXOptions_input.png JFXOptions_input_1.png

JFXOptions_password.png JFXOptions_password_1.png

the CSS file
Java:
/*
Joe Nartca (C)
For the JFXOptions
NOTE: if css file is a part of JFX application its should be preceded by the reference .css
Example:
.css .button {
    -fx-background-color:
        linear-gradient(#f0ff35, #a9ff00),
        radial-gradient(center 50% -40%, radius 200%, #b8ee36 45%, #80c800 50%);
    -fx-background-radius: 6, 5;
    -fx-background-insets: 0, 1;
    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.4) , 5, 0.0 , 0 , 1 );
    -fx-text-fill: #395306;
    -fx-font-size: 9pt;
}
.css .button:hover {
  -fx-background-color: bisque;
}
*/
.button {
    -fx-background-color:
        linear-gradient(#f0ff35, #a9ff00),
        radial-gradient(center 50% -40%, radius 200%, #b8ee36 45%, #80c800 50%);
    -fx-background-radius: 6, 5;
    -fx-background-insets: 0, 1;
    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.4) , 5, 0.0 , 0 , 1 );
    -fx-text-fill: #395306;
    -fx-font-size: 9pt;
}
.button:hover {
  -fx-background-color: bisque;
}
The full codes for download jfxoptions.zip
 

Attachments

Sửa lần cuối:

Joe

Thành viên VIP
21/1/13
2,958
1,323
113
Maybe you may ask yourself why I have designed JFXOptions for JavaFX when JOptions for SWING is available. The answer is simple: it's for the sake of JavaFX-LAF (Look And Feel). With the CSS file you can beautify the prompted LAF dialogs exactly like the JavaFX LAF application. All JOptions methods are static, so you can run JavaFA application and invoke SWING JOptions without any problem. Example:
Java:
public class JFXOptionsTest extends Application {
  public void start(Stage stage) {
    stage.setMinWidth(250);
    stage.setTitle("JFXOptions");
    //
    Button pla = new Button("input");
    pla.setOnAction(e -> {
      System.out.println(JFXOptions.input("css.css", "JFXOptions.input")); // JavaFX
    });
    ...
    Button pla1 = new Button("input");
    pla1.setOnAction(e -> {
      System.out.println(JOptions.input(null, "JOptions.input")); // SWING
    });
    ...
    vbox.getChildren().setAll(pla, .... pla1, ...);

    Scene scene = new Scene(vbox);
    stage.setScene(scene);
    stage.show();  
  }
Bild_2021-07-16_092613.png

However, all JFXOptions methods CANNOT BE INVOKED by SWING application, even the methods are static.

SWING_Exception.png

Reason is JavaJF requires a different initializer (see red arrow) and that is also the reason why JavaFX was separated from Java without any problem and becomes the Open Sources.
 
Sửa lần cuối: