JavaFX Controls Preview

The screenshot below is a preview of JavaFX Controls. It was created in Processing4 after adding the javafx.controls module to line 1086 of JavaBuild.java and recompiling the editor. The source code and output are shown below:

Source code:

import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.control.Spinner;
import javafx.scene.control.ListView;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Dialog;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Circle;
import java.time.LocalDate;

Pane pane;

Pane addControls() {
  // **** Pane **** //
  Pane pane = new Pane();

  // **** Label **** //
  Label label = new Label("Label");
  Font font = Font.font("Menlo", FontWeight.BOLD, FontPosture.REGULAR, 15);
  label.setFont(font);
  label.setTextFill(Color.RED);
  label.setTranslateX(70);
  label.setTranslateY(20);
  pane.getChildren().add(label);

  // **** Toggle Button **** //
  ToggleButton toggleBtn = new ToggleButton("Off");
  toggleBtn.setLayoutX(130);
  toggleBtn.setLayoutY(20);
  toggleBtn.selectedProperty().addListener(((observable, oldValue, newValue) -> {
    if (newValue == true) {
      toggleBtn.setText("On");
    } else {
      toggleBtn.setText("Off");
    }
  }
  ));
  pane.getChildren().add(toggleBtn);

  // **** Dialog with Button **** //
  Dialog<String> dialog = new Dialog<String>();
  dialog.setTitle("Error Dialog");
  ButtonType type = new ButtonType("Ok", ButtonData.OK_DONE);
  dialog.setContentText("Message goes here.");
  dialog.getDialogPane().getButtonTypes().add(type);
  Button btn = new Button("Push Me");
  btn.setLayoutX(350);
  btn.setLayoutY(140);
  btn.setOnAction(e -> {
    dialog.showAndWait();
  }
  );
  pane.getChildren().add(btn);

  // **** Circle **** //
  Circle circle = new Circle(400, 60, 20);
  circle.setFill(Color.GREEN);
  pane.getChildren().add(circle);

  // **** Slider **** //
  Slider slider = new Slider(1, 50, 10);
  slider.setLayoutX(190);
  slider.setLayoutY(20);
  Tooltip tooltip1 = new Tooltip("Sets radius");
  slider.setTooltip(tooltip1);
  slider.valueProperty().addListener(new ChangeListener<Number>() {
    public void changed(ObservableValue <?extends Number>observable, Number oldValue, Number newValue) {
      circle.setRadius((double)newValue);
    }
  }
  );
  pane.getChildren().add(slider);

  // **** Spinner **** //
  Spinner spinner = new Spinner(0, 255, 0);
  spinner.setPrefSize(70, 25);
  spinner.setLayoutX(480);
  spinner.setLayoutY(60);
  pane.getChildren().add(spinner);

  // **** ComboBox **** //
  ComboBox<String> combo = new ComboBox<String>();
  combo.setPromptText("Select One");
  ObservableList<String> list = combo.getItems();
  list.add("Java");
  list.add("C++");
  list.add("Python");
  list.add("Processing");
  combo.setLayoutX(560);
  combo.setLayoutY(60);
  pane.getChildren().add(combo);

  // **** ListView **** //
  ObservableList<String> items = FXCollections.observableArrayList("Item 1", "Item 2", "Item 3");
  ListView<String> listView = new ListView<String>(items);
  listView.setMaxSize(100, 80);
  listView.setLayoutX(30);
  listView.setLayoutY(80);
  pane.getChildren().add(listView);

  // **** TabPane **** //
  TabPane tabPane = new TabPane();
  tabPane.setLayoutX(30);
  tabPane.setLayoutY(190);
  Tab tab1 = new Tab("Tab 1");
  Tab tab2 = new Tab("Tab 2");
  Tab tab3 = new Tab("Tab 3");
  tab1.setContent(new Rectangle(200, 100, Color.BLUE));
  tab2.setContent(new Rectangle(200, 100, Color.RED));
  tab3.setContent(new Rectangle(200, 100, Color.GREEN));
  tabPane.getTabs().addAll(tab1, tab2, tab3);
  pane.getChildren().add(tabPane);

  // **** TextArea **** //
  TextArea txtArea = new TextArea();
  txtArea.setLayoutX(250);
  txtArea.setLayoutY(190);
  txtArea.setMaxSize(180, 130);
  pane.getChildren().add(txtArea);

  // **** RadioButton Group **** //
  TilePane radioPane = new TilePane(15, 15);
  ToggleGroup group = new ToggleGroup();
  RadioButton radio1 = new RadioButton("A");
  radio1.setToggleGroup(group);
  radio1.setSelected(true);
  RadioButton radio2 = new RadioButton("B");
  radio2.setToggleGroup(group);
  RadioButton radio3 = new RadioButton("C");
  radio3.setToggleGroup(group);
  radioPane.getChildren().addAll(radio1, radio2, radio3);
  radioPane.setLayoutX(150);
  radioPane.setLayoutY(100);
  pane.getChildren().add(radioPane);

  // **** CheckBox **** //
  CheckBox cBox = new CheckBox("Checkbox");
  cBox.setIndeterminate(false);
  cBox.setLayoutX(60);
  cBox.setLayoutY(50);
  pane.getChildren().add(cBox);

  // **** TextField **** //
  TextField txtFld = new TextField();
  txtFld.setLayoutX(150);
  txtFld.setLayoutY(140);
  pane.getChildren().add(txtFld);

  // **** MenuBar **** //
  Menu menu = new Menu("File");
  MenuItem menuItem1 = new MenuItem("Open");
  MenuItem menuItem2 = new MenuItem("Save");
  menu.getItems().addAll(menuItem1, menuItem2);
  MenuBar menuBar = new MenuBar();
  menuBar.getMenus().add(menu);
  pane.getChildren().add(menuBar);

  // **** ToolBar **** //
  ToolBar toolBar = new ToolBar();
  Button openBtn = new Button("Build");
  Button saveBtn = new Button("Run");
  toolBar.getItems().addAll(openBtn, saveBtn);
  toolBar.setLayoutX(450);
  Tooltip tbarTip = new Tooltip("ToolBar");
  toolBar.setTooltip(tbarTip);
  pane.getChildren().add(toolBar);

  // **** ProgressBar **** //
  ProgressBar pBar = new ProgressBar();
  pBar.setLayoutX(560);
  pBar.setLayoutY(20);
  pane.getChildren().add(pBar);

  // **** TreeView **** //
  TreeItem rootItem = new TreeItem("Pets");
  TreeItem dogItem = new TreeItem("Dogs");
  dogItem.getChildren().add(new TreeItem("Poodle"));
  dogItem.getChildren().add(new TreeItem("Collie"));
  dogItem.getChildren().add(new TreeItem("Bulldog"));
  rootItem.getChildren().add(dogItem);

  TreeItem catItem = new TreeItem("Cats");
  catItem.getChildren().add(new TreeItem("Siamese"));
  catItem.getChildren().add(new TreeItem("Ragdoll"));
  catItem.getChildren().add(new TreeItem("Persian"));
  rootItem.getChildren().add(catItem);

  TreeView treeView = new TreeView();
  treeView.setRoot(rootItem);
  treeView.setLayoutX(460);
  treeView.setLayoutY(110);
  treeView.setMaxSize(140, 230);
  //treeView.setShowRoot(false);
  treeView.setShowRoot(true);
  pane.getChildren().add(treeView);

  // **** ColorPicker **** //
  ColorPicker colorPicker = new ColorPicker();
  colorPicker.setLayoutX(200);
  colorPicker.setLayoutY(50);
  colorPicker.setValue(Color.GREEN);
  colorPicker.setOnAction(action -> {
    label.setTextFill(colorPicker.getValue());
    circle.setFill(colorPicker.getValue());
  }
  );
  pane.getChildren().add(colorPicker);

  // **** DatePicker **** //
  DatePicker datePicker = new DatePicker();
  datePicker.setLayoutX(30);
  datePicker.setLayoutY(350);
  datePicker.setOnAction(action -> {
    LocalDate value = datePicker.getValue();
  }
  );
  pane.getChildren().add(datePicker);

  // **** Line Chart **** //
  NumberAxis xAxis = new NumberAxis();
  xAxis.setLabel("No. of months");
  NumberAxis yAxis = new NumberAxis();
  yAxis.setLabel("Dollars Per Dozen");
  LineChart lineChart = new LineChart(xAxis, yAxis);
  XYChart.Series dataSeries1 = new XYChart.Series();
  dataSeries1.setName("2023");
  dataSeries1.getData().add(new XYChart.Data( 1, 2));
  dataSeries1.getData().add(new XYChart.Data( 2, 3));
  dataSeries1.getData().add(new XYChart.Data(3, 4));
  dataSeries1.getData().add(new XYChart.Data(4, 5));
  dataSeries1.getData().add(new XYChart.Data(5, 6));
  dataSeries1.getData().add(new XYChart.Data(6, 6));
  lineChart.getData().add(dataSeries1);
  lineChart.setTitle("Price of Eggs");
  lineChart.setLayoutX(280);
  lineChart.setLayoutY(350);
  lineChart.setMaxSize(320, 240);
  pane.getChildren().add(lineChart);

  return pane;
}

void setup() {
  size(1, 1, FX2D);
  Stage stage = new Stage();
  stage.setTitle("JavaFX Controls");
  pane = addControls();
  Scene scene = new Scene(pane, 700, 600);
  stage.setScene(scene);
  stage.show();
}

void draw() {
}

Output:

1 Like

!!
this sketch run nicely as the previous ones
it looks really great, full of promise

i tried println in draw(){} and it looks active,do you think its possible to interact from there with pane?
do you think multipleWindows is possible (P3D, javafx will be a dream)?
well… i guess you have a lot of stuff to tune, so i will be patient

:disappointed_relieved: 300% inflation on eggs -.-
(side note: i don t know if there is something like frameRate in javafx, it run full speed and use a full core here)

Thanks for the followup and taking the time to test it. I don’t know the answers to your questions, but will keep them in mind as we go forward. I’m impressed that you are able to run the code; did you use the technique of placing the jar files in the ‘code’ folder or were you able to use a re-compiled version of Processing4 by itself without a ‘code’ folder?

Found the following on the web:https://jenkov.com/tutorials/javafx/3d.html

Does this JavaFX 3D Example help any:

import javafx.application.Application;
import javafx.application.ConditionalFeature;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.shape.Box;
import javafx.scene.shape.CullFace;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;

void setup() {
  size(1, 1, FX2D);
  Stage stage = new Stage();
  stage.setTitle("JavaFX 3D example");
  boolean is3DSupported = Platform.isSupported(ConditionalFeature.SCENE3D);
  if (!is3DSupported) {
    println("Sorry, 3D is not supported in JavaFX on this platform.");
    return;
  }
  Box box = new Box(100, 100, 100);
  box.setCullFace(CullFace.NONE);
  box.setTranslateX(250);
  box.setTranslateY(100);
  box.setTranslateZ(400);
  boolean fixedEyeAtCameraZero = false;
  PerspectiveCamera camera = new PerspectiveCamera(fixedEyeAtCameraZero);
  camera.setTranslateX(150);
  camera.setTranslateY(-100);
  camera.setTranslateZ(250);
  Group root = new Group(box);
  root.setRotationAxis(Rotate.X_AXIS);
  root.setRotate(30);
  Scene scene = new Scene(root, 500, 300, true);
  scene.setCamera(camera);
  stage.setScene(scene);
  stage.show();
}

Output:

1 Like

it works too,
both on mac and windows
i didn’t play more with compilation so i tested on same version than previously:
all 1085 line modules added to 1086, no other changes before compilation

then pasted 8 javafx related jar in “code” directory, may be the point here is i put everything in the directory, i don t keep sub directory structure as i m not sure it link recursively this directory:
dir

I thought maybe the ability to use 3D in javafx might obviate the need to have a separate P3D window that you mentioned in your first post.

If you feel like experimenting, try running the code without the separate ‘code’ folder. I can’t tell if you are able to run the demo because you successfully re-compiled Processing4 or whether it is because you added the jar files to a ‘code’ folder. Whatever you did obviously worked, but it would be nice to know which of the two methods is responsible for your success. Thanks again.

i tried, but without “code” directory, even with recompiled processing, i get:

Libraries must be installed in a folder named 'libraries' inside the sketchbook folder (see the Preferences window).
The package “javafx” does not exist. You might be missing a library.

my guess is it need something more in javabuild to add this library path to main processing, a fast search for ‘javafx’ in javabuid show some lines about a specific treatment for javafx, no idea what is it about and i didn t dig more there
on you side, did you changed something else to get it work without “code” ?

I only changed one line of source code (line 1086 of JavaBuild.java) and then recompiled. When I had previously tried the code folder with jars method it failed on my system. I can’t understand why it failed for me but works for you unless it has something to do with the chip (intel vs. m1). When you created the ‘code’ folder did you do this manually or drag and drop a jar file into the Processing sketch screen, which would cause the runtime to create the folder for you? I notice you also added an additional javafx.jar file in addition to the seven javafx modules.

yes it s strange, moreover i have the same exact behaviour with windows machine

i create the directory in finder and copy pasted all the jars i found in processing library javafx

if you want i can try on an intel machine tomorrow…

oh may be this: first code you posted, before compilation, i tried by importing via normal processing import/manage libraries menu the javafx library present there, and as “contribution libraries” are common to whatever processing version, the new compiled one have access to it

i guess it can be that, i will do tests tomorrow

What you are doing is important for the future of javafx on this platform because I don’t know if the editor authors are going to add all seven modules to the source code or not. If they don’t do that then a technique which doesn’t require recompilation by the user would become important if we want anyone else to be able to use javafx controls. I’m not sure very many users have the interest or programming skill to modify and recompile the Processing4 editor, hence your technique would be much simpler to employ and would allow others to be able to use all of javafx’s capabilities.

1 Like