Good afternoon everyone. I usually try to find and fix mistakes myself, but this time I got stuck for real. My assignment was to write a loan calculator. All code was working and compiling just fine until I got to the point where I need to create a Line Diagram/Graph, which pops up in a new window.
The problem lies somewhere in loading FXML files or connecting Additional Controllers to the Main Controller.
I tried different approaches and checked in different forums for solution, but couldn't implement one into my code. Could anyone propose me a solution?
Here is my Main which launches the program.
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Scene.fxml"));
primaryStage.setTitle("Loan calculator");
primaryStage.setScene(new Scene(root, 770, 410));
primaryStage.setResizable(false);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This is my Main Controller. Little note. I understand that the way I use "initialize" method of my second controller in my main one is not correct, but I tried different approaches and they didn't give me any better result
public class Controller implements Initializable {
public static int years = 0;
public static int months = 0;
private double desiredLoan = 1; //should be set to zero,but for testing is set differently
private boolean graph = true; //true - linear, false - annuity
@FXML
private Button Button_3 = new Button();
private LineGraphController lineGraphController = new LineGraphController("Linear");
private AnnuityGraphController annuityGraphController = new AnnuityGraphController("Annuity");
/**Some code to count my data*/
@Override /** This method is used to access my UI elements and access other controllers*/
public void initialize(URL url, ResourceBundle resourceBundle) {
Button_3.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
try {
if (desiredLoan == 0 && months == 0 && years == 0) {
throw new RuntimeException();
}
else {
if (whatGraph() == true) { //make linear graph
lineGraphController.initialize(url, resourceBundle);
}
else {//make annuity graph
annuityGraphController.initialize(url, resourceBundle);
}
}
}
catch (RuntimeException error) {
error.printStackTrace();
}
}
});
}
/** Getters and setters */
public boolean whatGraph() {
return graph;
}
public void setGraph(boolean graph) {
this.graph = graph;
}
}
My main controllers:
Line Graph controller
/** This controller is used to load additional fxml file*/
public class LineGraphController implements Initializable {
@FXML
public LineChart<?, ?> LineGraph;
private String title;
public LineGraphController(String title) {
this.title = title;
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("LineGraph.fxml"));
Parent lineGraph = null;
try {
lineGraph = (Parent)fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
Stage window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle(title);
window.setResizable(false);
window.setMinWidth(600);
window.setMinHeight(400);
window.setScene(new Scene(lineGraph));
window.showAndWait();
}
}
Annuity Graph Controller
/** This controller is used to load additional fxml file*/
public class AnnuityGraphController implements Initializable {
@FXML
public LineChart<?, ?> AnnuityGraph;
private String title;
public AnnuityGraphController(String title) {
this.title = title;
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("AnnuityGraph.fxml"));
Parent lineGraph = null;
try {
lineGraph = (Parent)fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
Stage window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle(title);
window.setResizable(false);
window.setMinWidth(600);
window.setMinHeight(400);
window.setScene(new Scene(lineGraph));
window.showAndWait();
}
}
My Main FXML file.
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: #4a4a4a;" xmlns="http://javafx.com/javafx/10.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Paskolu_Skaiciuokle.Controller">
<center>
<Button fx:id="Button_3" maxWidth="150.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="100.0" style="-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.3), 3, 0,5, 5, 5);" text="Show graph" BorderPane.alignment="CENTER">
<font>
<Font name="Times New Roman" size="12.0" />
</font>
</Button>
</center>
</BorderPane>
My additional FXML files for controllers:
Line Graph FXML
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="670.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/10.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Loan_calculator.LineGraphController">
<!-- some code -->
</AnchorPane>
Annuity Graph FXML
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="670.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/10.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Loan_calculator.AnnuityGraphController">
<-- some code -->
</AnchorPane>
Thank you in advance for help.
p.s. These are the links in which I tried to look for solution, there were a lot of different ways to code this, but just couldn't find one which I could implement into my code.. or maybe I just lack knowledge of how to do it. Either way I hope someone will be able to help me or explain on how to fix this.
Links:
•Passing Parameters JavaFX FXML
•How to create multiple javafx controllers with different fxml files?
•Multiple FXML with Controllers, share object
My main problem is accessing additional controllers from my main controller. (All of the controllers are linked to their own FXML files).
I don't understand you problem very well, but I try to answer. I think you want to access other controller from main controller,simplest way is:
FXMLLoader mainLoader = new FXMLLoader(getClass().getResource("MainController.fxml"));
Parent main = mainLoader.load();
MainController mainController = mainLoader.getController();
FXMLLoader otherLoader = new FXMLLoader(getClass().getResource("OtherController.fxml"));
Parent other = otherLoader.load();
// set other controller in main controller
mainController.setOtherController(otherLoader.getController());
If you use javafx-weaver and spring boot, DI will make it more easy:
@Component
@FxmlView
class MainController {
@Autowired
private FxControllerAndView<OtherController, VBox> otherControllerAndView;
// otherControllerAndView.getController() to access other controller
}