JavaFX milti-windows exception - javafx

I've found such a problem:
Having a MainWindow and 2 SubWindows, but I've got exceptions like:
-Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
-Caused by: java.lang.NullPointerException: Location is required.
-[...]
-at ApplicationForTests.SubWin1.SubWin1.display(SubWin1.java:14)
> Parent root = FXMLLoader.load(getClass().getResource("ApplicationForTests/SubWin1UI.fxml"));
-[...]
-at ApplicationForTests.MainController.openSub1(MainController.java:22)
> subWin1.display();
-[...]
-Exception in thread "Thread-3" java.lang.IncompatibleClassChangeError
Main:
public class Main extends Application {
public static BdcsDAO db = new BdcsDAO();
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("MainUI.fxml"));
primaryStage.setTitle("Main window");
primaryStage.setScene(new Scene(root, 500, 400));
primaryStage.show();
db.connect();
}
public static void main(String[] args) {launch(args);}
MainController:
public class MainController {
#FXML
Button button1;
#FXML
Button button2;
#FXML
public void openSub1() {
SubWin1 subWin1 = new SubWin1();
try {
subWin1.display();
} catch (IOException e) {
e.printStackTrace();
}
}
#FXML
public void openSub2() {
SubWin2 subWin2 = new SubWin2();
try {
subWin2.display();
} catch (IOException e) {
e.printStackTrace();
}
}
}
MainUI:
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ApplicationForTests.MainController">
<children>
<Button fx:id="button1" onAction="#openSub1" layoutX="268.0" layoutY="185.0" mnemonicParsing="false" text="SubWin1" />
<Button fx:id="button2" onAction="#openSub2" layoutX="268.0" layoutY="285.0" mnemonicParsing="false" text="SubWin2" />
</children>
</AnchorPane>
SubWin1:
public class SubWin1 {
public void display() throws IOException {
Stage window = new Stage();
Parent root = FXMLLoader.load(getClass().getResource("ApplicationForTests/SubWin1UI.fxml"));
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle("Sub window no. 1");
window.setScene(new Scene(root, 800, 500));
window.show();
}
}
SubWin1Controller:
public class SubWin1Controller {
#FXML
Button button;
#FXML
public void loadTableView() throws SQLException {
setAlarmsTableView(Main.db.getSampleResultSet());
}
#FXML
private TableView<AlarmType> alarmsTableView;
#FXML
private TableColumn<?, ?> columnDeviceIndex;
#FXML
private TableColumn<?, ?> columnAlgorithmType;
private ObservableList<AlarmType> dataAlarms = FXCollections.observableArrayList();
public void setAlarmsTableView(ResultSet rs) throws SQLException {
columnDeviceIndex.setCellValueFactory(new PropertyValueFactory<>("deviceIndex"));
columnAlgorithmType.setCellValueFactory(new PropertyValueFactory<>("algorithmType"));
while (rs.next()) {
dataAlarms.add(new AlarmType(rs.getInt(1), rs.getInt(2));
}
alarmsTableView.setItems(dataAlarms);
}
}

Related

issue with using extended JavaFX Class Dialog<R> and initializing the DialogPane

I use an extended Dialog class in my JavaFX application, but I failed to initialize the fields of the DialogPane. It seems the initialize method is never invoked. I make several modifications of the program code, unfortunately I do not have success. Therefore I hope you can help me. Thanks!
The application is reduced to a minimum: the main program starts via ControllerFactory the PortalController. There is a button to open my 'DialogFriZi'. The related DialogPane contains a label. The initializing of this label failed.
main program:
public class Main extends Application {
private final Logger logger = Logger.getLogger(this.getClass().getName());
private final String FXML_PORTAL = "portal.fxml";
private MyHandler myHandler = new MyHandler();
#Override
public void init() {
try{
// Thread.currentThread is the FX-Launcher thread:
Thread.currentThread().setUncaughtExceptionHandler(myHandler);
try {
logger.addHandler(new FileHandler("java.myLOG"));
}
catch (IOException e) {
throw new IllegalStateException("IOException when adding File Handler");
}
}
catch (Exception ex) {
myHandler.uncaughtException(Thread.currentThread(), ex);
throw(ex);
}
}
#Override
public void start(Stage primaryStage) {
try{
logger.info("Test Application started");
Thread.currentThread().setUncaughtExceptionHandler(myHandler);
try{
URL location = new URL(this.getClass().getResource("resources/fxml/" + FXML_PORTAL).toString());
FXMLLoader loader = new FXMLLoader(location);
loader.setControllerFactory(new SimpleControllerFactory(primaryStage));
Pane root = loader.load();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setTitle("*** TEST App ***");
primaryStage.show();
}
catch(IOException ex) {
ex.printStackTrace();
throw new IllegalStateException("check program source code!");
}
}
catch(Exception ex) {
myHandler.uncaughtException(Thread.currentThread(), ex);
throw(ex);
}
}
public static void main(String[] args) {
launch(args);
}
class MyHandler implements Thread.UncaughtExceptionHandler{
#Override
public void uncaughtException(Thread thread, Throwable throwable) {
logger.log(Level.SEVERE, "** STOPP ** due to uncaught exception", throwable);
Platform.exit();
}
}
}
ControllerFactory
public class SimpleControllerFactory implements Callback<Class<?>,Object> {
private static final Logger logger = Logger.getLogger(SimpleControllerFactory.class.getName());
private final Stage primaryStage;
// types of controller
public SimpleControllerFactory(Stage stage) {
this.primaryStage = stage;
}
public SimpleControllerFactory() { this(null); }
#Override
public Object call(Class<?> type) {
try {
for (var c : type.getConstructors()) {
switch(c.getParameterCount()) {
case 0 -> { }
case 1 -> {
if ( c.getParameterTypes()[0] == Stage.class) {
return c.newInstance(primaryStage) ;
}
else;
}
default -> { }
}
}
return type.getDeclaredConstructor().newInstance();
}
catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException ex) {
logger.log(Level.SEVERE,ex.toString(),ex);
throw new RuntimeException(ex);
}
}
}
PortalController
public class PortalController implements Initializable {
private static final Logger logger = Logger.getLogger(PortalController.class.getName());
private final Stage recentStage;
private ResourceBundle resourceBundle;
public PortalController(Stage stage) {
this.recentStage = stage;
}
public PortalController() {
this(null);
}
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
}
#FXML
private void start(ActionEvent event) {
DialogFriZi dialog = null;
dialog = new DialogFriZi(recentStage);
Optional<Boolean> result = dialog.showAndWait();
}
}
related FXML file
<VBox prefHeight="500.0" prefWidth="400.0" spacing="5.0" style="-fx-padding: 5 5 5 5;-fx-font-size: 11px" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="TestSimpleDialog.PortalController">
<children>
<HBox alignment="CENTER">
<children>
<Button mnemonicParsing="false" onAction="#start" text="start FriZi dialog">
<HBox.margin>
<Insets top="50.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</children>
the extended Dialog class
public class DialogFriZi extends Dialog<Boolean> {
#FXML private ButtonType okButtonType;
#FXML Label label;
private static final Logger logger = Logger.getLogger(DialogFriZi.class.getName());
private final Stage recentStage;
public DialogFriZi(Stage primaryStage) {
this.recentStage = primaryStage;
runDialog();
}
public DialogFriZi() {
this(null);
}
#FXML private void initialize() {
System.out.println("start initializing");
label.setText("hello");
}
private void runDialog() {
FXMLLoader loader = new FXMLLoader();
try {
loader.setLocation(new URL
(this.getClass().getResource("resources/fxml/dialogFriZi.fxml").toString()));
DialogPane dialogPane = loader.load();
loader.setController(this);
initOwner(recentStage);
initModality(Modality.APPLICATION_MODAL);
setResizable(true);
setTitle("FriZi Dialog");
setDialogPane(dialogPane);
}
catch (IOException e) {
String message = "illegale state due to problem with 'resource dialogFriZi.fxml'";
logger.log(Level.SEVERE,message);
throw new IllegalStateException(message);
}
}
}
related FXML file
<DialogPane prefHeight="400.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1">
<content>
<HBox prefHeight="100.0" prefWidth="200.0">
<children>
<Label fx:id="label" text="Label" />
</children></HBox>
</content>
<buttonTypes>
<ButtonType buttonData="OK_DONE" text="ok" />
<ButtonType buttonData="CANCEL_CLOSE" text="Abbrechen" />
</buttonTypes>
The initalize() method is invoked on the controller, if there is one, during the execution of the load() method. You are setting the controller after calling load(), so when load() runs, there is no controller. You need to change the order of the calls:
private void runDialog() {
FXMLLoader loader = new FXMLLoader();
try {
loader.setLocation(new URL
(this.getClass().getResource("resources/fxml/dialogFriZi.fxml").toString()));
loader.setController(this);
DialogPane dialogPane = loader.load();
// loader.setController(this);
initOwner(recentStage);
initModality(Modality.APPLICATION_MODAL);
setResizable(true);
setTitle("FriZi Dialog");
setDialogPane(dialogPane);
}
catch (IOException e) {
String message = "illegale state due to problem with 'resource dialogFriZi.fxml'";
logger.log(Level.SEVERE,message);
throw new IllegalStateException(message);
}
}

selectFirst() on javafx ListView dont select the element

i have small application to manage my tasks. I created DB(sqlite), and i store there a data.
After i log in i got dashboard scene. On dashboard scene i have implemented ObservableList which store taskList and their details. This list is updated always when i add/modify/delete tasks.
I have problem when i add/modify/delete task, when i do it the list is correctly updated but the item witch i add/modify is not selected after operation although i have that implemented.
The Main code:
public class Main extends Application {
private static Main instance;
public BorderPane mainBorderPane;
private Stage primaryStage;
public static Main getInstance() {
return instance;
}
#Override
public void start(Stage primaryStage) throws Exception{
instance = this;
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Hello World");
showDashboardScene();
}
private void showDashboardScene() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/sample/dashboard.fxml"));
mainBorderPane = loader.load();
Scene scene = new Scene(mainBorderPane);
primaryStage.setScene(scene);
primaryStage.initStyle(StageStyle.UTILITY);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
DashboardController:
public class DashboardController {
private ObservableList<Task> tasks = FXCollections.observableArrayList();
#FXML
private ListView<Task> taskListView;
public void initialize() throws SQLException {
tasks = TaskData.getInstance().getTaskList();
findListChange();
taskListView.setItems(tasks);
taskListView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
taskListView.getSelectionModel().selectFirst();
}
public void refreshView() {
tasks = TaskData.getInstance().getTaskList();
findListChange();
taskListView.setItems(tasks);
taskListView.getSelectionModel().selectedItemProperty();
taskListView.getSelectionModel().selectLast();
}
private void findListChange() {
this.taskListView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Task>() {
#Override
public void changed(ObservableValue<? extends Task> observable, Task oldValue, Task newValue) {
if (newValue != null) {
Task item = taskListView.getSelectionModel().getSelectedItem();
}
}
});
}
}
dashboard.fxml
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.ListView?>
<BorderPane fx:controller="sample.DashboardController" xmlns:fx="http://javafx.com/fxml" >
<top>
<fx:include fx:id="mainMenu" source="/sample/menu.fxml"/>
</top>
<left>
<ListView fx:id="taskListView"/>
</left>
</BorderPane>
MenuController
public class MenuController {
public void showDialog() throws SQLException, IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/sample/addTask.fxml"));
loader.load();
AddTaskController controller = loader.getController();
controller.showAddTaskDialog();
}
}
menu.fxml
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuItem?>
<MenuBar fx:controller="sample.MenuController" xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml ">
<Menu text="Tasks">
<MenuItem text="Add" onAction="#showDialog"/>
</Menu>
</MenuBar>
addTask.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.GridPane?>
<DialogPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
fx:controller="sample.AddTaskController">
<content>
<GridPane vgap="10" hgap="10" >
<Label text="Name" GridPane.rowIndex="0" GridPane.columnIndex="0"/>
<TextField fx:id="taskNameTF" GridPane.rowIndex="0" GridPane.columnIndex="1"/>
</GridPane>
</content>
</DialogPane>
AddTaskController:
public class AddTaskController {
#FXML
private TextField taskNameTF;
#FXML
public void showAddTaskDialog()throws IOException, SQLException {
Dialog<ButtonType> dialog = new Dialog<>();
dialog.initOwner(Main.getInstance().mainBorderPane.getScene().getWindow());
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/sample/addTask.fxml"));
try {
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {e.printStackTrace();
System.out.println("Nie udało sie wyświetlić panelu, prosimy spróbować później");
e.printStackTrace();
return;
}
dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
Optional<ButtonType> result = dialog.showAndWait();
if(result.isPresent() && result.get().equals(ButtonType.OK)) {
AddTaskController controller = loader.getController();
controller.addTaskToList();
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("/sample/dashboard.fxml"));
fxmlLoader.load();
DashboardController dashboardController = fxmlLoader.getController();
dashboardController.refreshView();
System.out.println("OK, pressed");
} else {
System.out.println("CANCEL, pressed");
}
}
private void addTaskToList() {
String taskName = taskNameTF.getText().trim();
TaskData.getInstance().addTaskToList(new Task(taskName));
}
}
Task
public class Task {
private String taskName;
public Task(String taskName) {
this.taskName = taskName;
}
#Override
public String toString() {
return taskName.toString();
}
}
TaskData
public class TaskData {
private ObservableList<Task> tasks = FXCollections.observableArrayList();
private static TaskData instance = new TaskData();
public static TaskData getInstance() {
return instance;
}
public ObservableList<Task> getTaskList() {
return tasks;
}
public void addTaskToList(Task task) {
instance.tasks.add(task);
}
}
i'm not sure but when i initialize a application, reference to ListView is different than reference of list when i add/modify item. I think this is the problem but i dont know how to fix it ;/

How to add a javafx shortcut key combinations for buttons

My UI has a adding button and I want to assign a keyboard shortcut combination for that. I have failed to use the setAcceleartor for this purpose.
What is the easiest way to set up keyboard shortcuts in javafx applications?
button declaration in the UI:
<Button fx:id="addButton" alignment="CENTER" minWidth="-Infinity" mnemonicParsing="false" onAction="#addAction" prefHeight="31.0" prefWidth="130.0" text="Add" HBox.hgrow="ALWAYS" />
Controller button binding:
#FXML
private Button addButton;
The method that wants to setOnAction for the shortcut for the button:
public void addAction(ActionEvent event) throws SQLException, ClassNotFoundException {
if (validateInput()) {
String productName = productField.getText();
double unitPrice = Double.parseDouble(priceField.getText());
int quantity = Integer.parseInt(quantityField.getText());
double total = unitPrice * quantity;
ITEMLIST.add(new Item(productName, unitPrice, quantity, total));
calculation();
resetAdd();
productTableView.getSelectionModel().clearSelection();
ObservableList<Product> productsData = ProductDAO.searchProducts();
populateProducts(productsData);
searchField.setText("");
}
}
initialize() method:
#FXML
private void initialize() throws SQLException, ClassNotFoundException, IOException {
setSaveAccelerator(addButton);
}
The code I tried with setAccelerator:
private void setSaveAccelerator(final Button button) {
Scene scene = button.getScene();
if (scene == null) {
throw new IllegalArgumentException("setSaveAccelerator must be called when a button is attached to a scene");
}
scene.getAccelerators().put(
new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN),
new Runnable() {
#FXML public void run() {
button.fire();
}
}
);
}
In your setSaveAccelerator method, instead of directly calling addAction(ActionEvent event), just instruct the button to fire its event to its listeners such as: button.fire(). For example:
private void setSaveAccelerator(Button button) {
if(button==null) {
System.out.println("Button is null! "); // check that the button was injected properly through your fxml
}
Scene scene = button.getScene();
if (scene == null) {
throw new IllegalArgumentException("setSaveAccelerator must be called when a button is attached to a scene");
}
scene.getAccelerators().put(
new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN),
new Runnable() {
#FXML public void run() {
button.fire();
}
}
);
}
EDIT
To also avoid the IllegalArgumentException you must attach the accelerator after the button is attached to a scene. I managed to achieve this by creating a public method in the controller to attach the accelerator after the scene has been set. Then, in the class where the scene is loaded the controller's method can be called which sets up this functionality. See the example below:
In the controller class (in my case MainController):
public void setup() {
setSaveAccelerator(button);
}
In your main class when loading the fxml file:
FXMLLoader loader = new FXMLLoader(MainController.class.getResource("mainFXML.fxml"));
AnchorPane page = (AnchorPane) loader.load();
MainController controller = loader.getController();
Scene scene = new Scene(page);
controller.setup(); // calls the setup method attaching the accelerators
FULL EXAMPLE
Main class:
public class Main extends Application{
public static Stage primaryStage;
#Override
public void start(Stage primaryStage) throws Exception {
Main.primaryStage=primaryStage;
FXMLLoader loader = new FXMLLoader(MainController.class.getResource("mainFXML.fxml"));
AnchorPane page = (AnchorPane) loader.load();
MainController controller = loader.getController();
Scene scene = new Scene(page);
primaryStage.setTitle("Shortcut example");
primaryStage.setScene(scene);
controller.setup();
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Maincontroller:
public class MainController {
#FXML
private ResourceBundle resources;
#FXML
private URL location;
#FXML
private Button button;
#FXML
private AnchorPane rootPane;
#FXML
private TextArea textarea;
#FXML
void action(ActionEvent event) {
textarea.setText("Action fired!!");
}
#FXML
void initialize() {
assert button != null : "fx:id=\"button\" was not injected: check your FXML file 'MainFXML.fxml'.";
assert rootPane != null : "fx:id=\"rootPane\" was not injected: check your FXML file 'MainFXML.fxml'.";
assert textarea != null : "fx:id=\"textarea\" was not injected: check your FXML file 'MainFXML.fxml'.";
}
public void setup() {
setSaveAccelerator(button);
}
private void setSaveAccelerator(Button button) {
if(button==null) {
System.out.println("Button null!!");
}
Scene scene = button.getScene();
if (scene == null) {
throw new IllegalArgumentException("setSaveAccelerator must be called when a button is attached to a scene");
}
scene.getAccelerators().put(
new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN),
new Runnable() {
#FXML public void run() {
button.fire();
}
}
);
}
}
MainFXML.fxml
<AnchorPane fx:id="rootPane" prefHeight="408.0" prefWidth="330.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<children>
<Button fx:id="button" layoutX="139.0" layoutY="350.0" mnemonicParsing="false" onAction="#action" text="Button" />
<TextArea fx:id="textarea" layoutX="73.0" layoutY="38.0" prefHeight="200.0" prefWidth="200.0" />
</children>
</AnchorPane>

javaFX - how to use function or object of a controller from another controller

I have seen a lot of question similar to mine, but I didn't figure it out how to solve my problem, so there is my code:
I have a simple main:
MainClassFXGui.java
public class MainClassFXGui extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("MyProgramMainGuiTab.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Assicurazione");
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
and three fxml files, one of them that contains the other two, by the tag
<fx:include source="MyTab1.fxml" />
MyProgramMainGuiTab.fxml
...
<TabPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="5000.0" prefWidth="5000.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab closable="false" text="MyTab1">
<content>
<fx:include source="MyTab1.fxml" />
</content>
</Tab>
<Tab closable="false" text="MyTab2">
<content>
<fx:include source="MyTab2.fxml" />
</content>
</Tab>
</tabs>
</TabPane>
...
and three controller:
MyProgramMainGuiTabController.java
....
#FXML
private Label LeftSt;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
LeftSt.setText("");
}
public void setLeftSt(String st){
LeftSt.setText(st);
}
...
MyTab1Controller.java
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
setLeftSt("Can I change the label of the MyProgramMainGuiTabController?");
}
I tried in this way:
MyTab1Controller.java
private MyProgramMainGuiTabController controller;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
controller.setLeftSt("Can I change the label of the MyProgramMainGuiTabController?");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
FXMLLoader fxmlLoader = new
FXMLLoader(getClass().getResource("MyProgramMainGuiTab.fxml"));
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
controller = (MyProgramMainGuiTabController)fxmlLoader.getController();
}
But I have a null pointer exception or if I move the code for the instanzialization of the object 'controller' in the handleButtonAction function, I don't have any error, but the label does not change.
Maybe I can create a static Scene and a static Stage in the MainClassFXGui.java?
but then I don't know how I could use them...
MainClassFXGui.java
public class MainClassFXGui extends Application {
static private Scene scene;
static private Stage stage;
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("MyProgramMainGuiTab.fxml"));
this.scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Assicurazione");
stage.show();
this.stage = stage;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public static Scene getScene(){
return AssicurazioneFXGui.scene;
}
public static Stage getStage(){
return AssicurazioneFXGui.stage;
}
}
can I do something with getScene() or getStage()? any idea or suggest?
thanks to everyone
Define a StringProperty in MyTab1Controller, with the usual methods:
public class MyTab1Controller {
private final StringProperty leftSt = new SimpleStringProperty();
public StringProperty leftStProperty() {
return leftSt ;
}
public final String getLeftSt() {
return leftStProperty().get();
}
public final void setLeftSt(String leftSt) {
leftStProperty().set(leftSt);
}
// ...
#FXML
public void handleButtonAction() {
setLeftSt(...);
}
// ...
}
Now assign an fx:id attribute to the fx:include tag:
<Tab closable="false" text="MyTab1">
<content>
<fx:include fx:id="myTab1" source="MyTab1.fxml" />
</content>
</Tab>
This means you can inject the controller for MyTab1.fxml into the controller for the FXML where it is included (MyProgramMainGuiTabController):
public class MyProgramMainGuiTabController {
#FXML
private MyTab1Controller myTab1Controller ;
}
and then you can just observe the property and update the label when it changes:
public class MyProgramMainGuiTabController {
#FXML
private MyTab1Controller myTab1Controller ;
#FXML
private Label leftSt;
public void initialize() {
leftSt.setText("");
myTab1Controller.leftStProperty().addListener((obs, oldValue, newValue) ->
leftSt.setText(newValue));
}
}
Note the rule here is that the field name for the controller is the value of the fx:id attribute with the word "Controller" appended: myTab1 in the fx:id resolves to myTab1Controller for the field where the controller is injected. See NestedControllers for more information.
At the moment I have solved in this way. If anyway someone has a better solution, please write. Also because this does not solve the problem if I need to execute a function.. thanks
MyProgramMainGuiTabController.fxml
...
#FXML
private Label LeftSt;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
LeftSt.setText("");
}
...
MyTab1Controller.fxml
#FXML
private Button myObject;
private Scene scene;
private Label lblDataLeft;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
setLeftSt("this works!");
}
public void setLeftSt(String st){
if(this.scene == null)
this.scene = myObject.getScene();
if(this.lblDataLeft==null)
this.lblDataLeft = (Label) scene.lookup("#LeftSt");
if (this.lblDataLeft!=null)
this.lblDataLeft.setText(st);
}

On Mouse Entered Method to swap Button position

I would like to develop a mouse entered method that swaps the locations of two buttons in real time using FXML and JavaFX which I am unfortunately very new to. Relocate(x,y), get/setLayoutX/Y and below get/setTranslateX/Y all throw IllegalArgumentEceptions with not much more understandable information in the stack trace. What is the preferred Button Property to use in order to get and then set a real-time location swap?
#FXML protected void neinHover (ActionEvent evt){
double jTmpX, jTmpY, nTmpX, nTmpY;
nTmpX = neinButton.getTranslateX();
nTmpY = neinButton.getTranslateY();
jTmpX = jaButton.getTranslateX();
jTmpY = jaButton.getTranslateY();
jaButton.setTranslateX(nTmpX);
jaButton.setTranslateY(nTmpY);
neinButton.setTranslateX(jTmpX);
neinButton.setTranslateY(jTmpY);
}
I supose you want something like this:
FXML:
<fx:root onMouseClicked="#swap" type="Pane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<children>
<Button fx:id="b1" mnemonicParsing="false" text="1" />
<Button fx:id="b2" layoutX="90.0" mnemonicParsing="false" text="2" />
</children>
</fx:root>
Controller:
public class MockPane extends Pane {
#FXML
private Button b1;
#FXML
private Button b2;
public MockPane() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(
"MockPane.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#FXML
private void swap() {
double b1x = b1.getLayoutX();
double b1y = b1.getLayoutY();
double b2x = b2.getLayoutX();
double b2y = b2.getLayoutY();
b1.setLayoutX(b2x);
b1.setLayoutY(b2y);
b2.setLayoutX(b1x);
b2.setLayoutY(b1y);
}
}
App:
public class MockApp extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage stage) throws Exception {
MockPane root = new MockPane();
Scene scene = new Scene(root, 200, 100);
stage.setScene(scene);
stage.show();
}
}

Resources