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

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);
}
}

Related

Update structure JavaFX TreeTableView

I create two windows and pass the Instance controller to the child window as a parameter. My problem is updating on the fly. I tried calling the refresh() method on treeTblState but nothing came of it.
First window
<AnchorPane xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="mo.specdoc.controllers.StateController">
<children>
<TreeTableView fx:id="treeTblState" showRoot="false">
<columns>
....
</columns>
</TreeTableView>
</children>
</AnchorPane>
Controller
public class StateController implements Initializable {
private static Map<Long, TreeItem> subdivisions = new HashMap<>();
private static StateController instance;
#FXML private TreeTableColumn<StateEntity, String> tblClmnTitle,...,tblClmnDelete;
#FXML private TreeTableView<StateEntity> treeTblState = new TreeTableView<>();
//Create root element (property setShow = false в FXML)
private StateEntity root = new StateEntity(0L,"State");
//Pattern Instance
public static StateController getInstance() {
if (instance == null) {
instance = new StateController();
}
return instance;
}
#Override
public void initialize(URL location, ResourceBundle resources) {
try {
tblClmnTitle.setCellValueFactory(new TreeItemPropertyValueFactory<>("postName"));
...
tblClmnDelete.setCellValueFactory(new TreeItemPropertyValueFactory<>("delete"));
treeGreate();
} catch ....
}
public void addChildren(StateEntity state) {
TreeItem<StateEntity> item = null;
for (Long key : subdivisions.keySet()) {
if (key == state.getSubdivisionId()) {
TreeItem<StateEntity> subdiv = subdivisions.get(key);
item = new TreeItem<StateEntity>(state);
subdiv.getChildren().add(item);
}
}
}
private void treeGreate() {
TreeItem<StateEntity> itemRoot = new TreeItem<StateEntity>(root);
treeTblState.setRoot(itemRoot);
//create tree - level 2
//subdivisions
for (SubdivisionEntity subdivision : subdivisionDAO.findAll()) {
StateEntity state = new StateEntity(
subdivision.getId(),
subdivision.getTitle()
);
state.getAdd().setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
createScene("Add post", new StateEntity(), subdivision.getId());
}
});
TreeItem<StateEntity> subdiv = new TreeItem<StateEntity>(state);
itemRoot.getChildren().add(subdiv);
subdivisions.put(state.getSubdivisionId(), subdiv);
//posts
List<StateEntity> childrens = stateDAO.findByIdSubdiv(state.getSubdivisionId());
if (!childrens.isEmpty()) {
for (StateEntity child : childrens) {
TreeItem<StateEntity> item = new TreeItem<StateEntity>(child);
subdiv.getChildren().add(item);
}
}
}
}
private void createScene(String title, StateEntity state, Long subdivisionId) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/state-edit.fxml"));
StateEditController stateEditController = new StateEditController(state, subdivisionId);
loader.setController(stateEditController);
Stage stage = new Stage();
Scene scene = new Scene(loader.load());
stage.setScene(scene);
stage.initModality(Modality.APPLICATION_MODAL);
stage.showAndWait();
} catch ....
}
}
Result
Second window
<AnchorPane xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1">
<children>
...elements...
</children>
</AnchorPane>
Controller
public class StateEditController implements Initializable {
....
#FXML
void saveAction(ActionEvent event) {
currentEntry.setSubdivisionId(subdivisionId);
currentEntry.setMaxAmountPersonal(cmbBoxMaxAmount.getSelectionModel().getSelectedItem().intValue());
currentEntry.setMinAmountPersonal(cmbBoxMaxAmount.getSelectionModel().getSelectedItem().intValue());
currentEntry.setAmplification(tglSwitchAmpl.isSelected());
currentEntry.setPostId(cmbBoxPost.getSelectionModel().getSelectedItem().getId());
if (currentEntry.getId() == null) {
stateDAO.save(currentEntry);
} else {
stateDAO.update(currentEntry);
}
stateController.addChildren(currentEntry); //call instance metod
}
#Override
public void initialize(URL location, ResourceBundle resources) {
....
}
}
Result
Everything is entered into the database successfully, but it is not updated when the window is closed 2.
I redraw the child elements using the clear method when adding an item
public void addChildren(StateEntity state) {
subdivisions.get(state.getSubdivisionId()).getChildren().clear();
List<StateEntity> childrens = stateDAO.findByIdSubdiv(state.getSubdivisionId());
if (!childrens.isEmpty()) {
for (StateEntity child : childrens) {
TreeItem<StateEntity> item = new TreeItem<StateEntity>(child);
subdivisions.get(state.getSubdivisionId()).getChildren().add(item);
}
}
}

Issue with passing constructor parameter via controller factory

I've got an issue with passing parameters to controller. The main program uses a controller factory to pass a stage object to my controller. The controller factory prints the address of the stage object, but the controller gets Null as stage object. Why ?
Though I've reduced my application to a simple dialogue, I can't find my fault. I hope you can help. Thanks!
The main program:
public class Main extends Application {
private final Logger logger = Logger.getLogger(this.getClass().getName());
private final String FXML_SIMPLE_DIALOG = "testDialog.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_SIMPLE_DIALOG).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();
}
}
}
The code of the controller factory:
public class SimpleControllerFactory implements Callback<Class<?>,Object> {
private static final Logger logger = Logger.getLogger(SimpleControllerFactory.class.getName());
private final Stage primaryStage;
public SimpleControllerFactory(Stage stage) {
this.primaryStage = stage;
System.out.println("controller factory: value of stage: " + this.primaryStage);
}
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);
}
}
}
This are the FXML-file and the simple controller:
<VBox prefHeight="150.0" prefWidth="250.0" spacing="5.0" style="-fx-padding: 5 5 5 5;-fx-font-size: 11px"
xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="TestSimpleDialog.DialogController">
<children>
<ButtonBar buttonOrder="UL_HE+FBIX_NCYOA_R" prefHeight="40.0">
<buttons>
<Button alignment="CENTER" mnemonicParsing="false" onAction="#time" text="time ?">
</Button>
</buttons>
</ButtonBar>
<StackPane VBox.vgrow="ALWAYS">
<children>
<Label fx:id="textTime" alignment="CENTER" text="" />
</children>
</StackPane>
</children>
simple controller:
public class DialogController implements Initializable {
private static final Logger logger = Logger.getLogger(DialogController.class.getName());
private final Stage recentStage;
DialogController(Stage stage) {
this.recentStage = stage;
}
DialogController() { this(null); }
#FXML private Label textTime;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
System.out.println("Controller started, value of recentStage: " + this.recentStage);
}
#FXML
private void time(ActionEvent event) {
textTime.setText(LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy kk:mm:ss")));
}
}
The Class.getConstructors() method
Returns an array containing Constructor objects reflecting all the public constructors of the class represented by this Class object.
(my emphasis).
Since your constructors are not declared public, the for loop in the factory's call(...) method iterates zero times, and it defaults to the call to the no-arg constructor.
Just declare the constructors as public and it will work:
public class DialogController implements Initializable {
private final Stage recentStage;
public DialogController(Stage stage) {
this.recentStage = stage;
}
public DialogController() { this(null); }
// ...
}
If you really want to keep the constructors non-public, you can us the getDeclaredConstructor(...) method to retrieve a specific constructor, which does not have to be public:
#Override
public Object call(Class<?> type) {
try {
System.out.println("Number of constructors found: "+type.getConstructors().length);
try {
Constructor<?> c = type.getDeclaredConstructor(Stage.class);
return c.newInstance(primaryStage);
} catch (NoSuchMethodException e) {
return type.getDeclaredConstructor().newInstance();
}
}
catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException ex) {
logger.log(Level.SEVERE,ex.toString(),ex);
throw new RuntimeException(ex);
}
}

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 ;/

JavaFX milti-windows exception

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);
}
}

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