Created
March 31, 2021 18:07
-
-
Save jondef/80a662ae5c74fcd56f260d66e0d8a0a4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ch.zhaw.prog2.fxmlcalculator; | |
import javafx.application.Application; | |
import javafx.fxml.FXMLLoader; | |
import javafx.scene.Parent; | |
import javafx.scene.Scene; | |
import javafx.stage.Stage; | |
import java.io.IOException; | |
/** | |
* Main-Application. Opens the first window (MainWindow) and the common ValueHandler | |
* @author | |
* @version 1.0 | |
*/ | |
public class Main extends Application { | |
private ValueHandler valueHandler; | |
public static void main(String[] args) { | |
launch(args); | |
} | |
@Override | |
public void start(Stage primaryStage) { | |
valueHandler = new ValueHandler(); | |
mainWindow(primaryStage); | |
} | |
private void mainWindow(Stage primaryStage) { | |
try { | |
Parent root = FXMLLoader.load(getClass().getResource("MainWindow.fxml")); | |
Scene scene = new Scene(root); | |
primaryStage.setTitle("Return on investment calculator"); | |
primaryStage.setScene(scene); | |
primaryStage.setMinWidth(250); | |
primaryStage.setMinHeight(350); | |
primaryStage.show(); | |
} catch (IOException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<?import javafx.geometry.*?> | |
<?import javafx.scene.control.*?> | |
<?import javafx.scene.input.*?> | |
<?import javafx.scene.layout.*?> | |
<AnchorPane xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.prog2.fxmlcalculator.MainWindowController"> | |
<BorderPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> | |
<top> | |
<MenuBar fx:id="menuBar" BorderPane.alignment="TOP_LEFT"> | |
<Menu text="Clear"> | |
<CheckMenuItem fx:id="checkmenuitem_clear_initial_amount" text="Initial amount" /> | |
<CheckMenuItem fx:id="checkmenuitem_return_in_percent" text="Return in %" /> | |
<CheckMenuItem fx:id="checkmenuitem_annual_cost" mnemonicParsing="false" text="Annual Costs" /> | |
<CheckMenuItem fx:id="checkmenuitem_number_years" mnemonicParsing="false" text="Number of years" /> | |
<SeparatorMenuItem /> | |
<MenuItem fx:id="menuitem_clear_values" text="Clear values" /> | |
<SeparatorMenuItem /> | |
<MenuItem fx:id="menuitem_clear_results" text="Clear results" /> | |
</Menu> | |
<Menu text="?"> | |
<MenuItem fx:id="menuitem_show_help" text="Show Help"> | |
<accelerator> | |
<KeyCodeCombination alt="UP" code="F1" control="UP" meta="UP" shift="UP" shortcut="UP" /> | |
</accelerator> | |
</MenuItem> | |
</Menu> | |
</MenuBar> | |
</top> | |
<center> | |
<VBox spacing="10.0"> | |
<HBox alignment="CENTER_LEFT"> | |
<Label minWidth="100.0" text="Initial amount" /> | |
<TextField fx:id="textfield_initial_amount" /> | |
</HBox> | |
<HBox alignment="CENTER_LEFT"> | |
<Label contentDisplay="CENTER" minWidth="100.0" text="Return rate in %" /> | |
<TextField fx:id="textfield_return_rate" /> | |
</HBox> | |
<HBox alignment="CENTER_LEFT"> | |
<Label minWidth="100.0" text="Annual cost" /> | |
<TextField fx:id="textfield_annual_cost" /> | |
</HBox> | |
<HBox alignment="CENTER_LEFT"> | |
<Label minWidth="100.0" text="Number of years" /> | |
<TextField fx:id="textfield_number_of_years" /> | |
</HBox> | |
<VBox alignment="CENTER_LEFT" VBox.vgrow="ALWAYS"> | |
<Label text="Results" /> | |
<TextArea fx:id="textarea_results" editable="false" VBox.vgrow="ALWAYS" /> | |
</VBox> | |
<BorderPane.margin> | |
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> | |
</BorderPane.margin> | |
</VBox> | |
</center> | |
<bottom> | |
<HBox alignment="CENTER" spacing="10"> | |
<Button fx:id="button_calculate" text="Calculate" /> | |
<Button fx:id="button_close" text="Close" /> | |
<Button fx:id="button_open_results" text="Results" /> | |
<BorderPane.margin> | |
<Insets bottom="10.0" left="10.0" right="10.0" /> | |
</BorderPane.margin> | |
</HBox> | |
</bottom> | |
</BorderPane> | |
</AnchorPane> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ch.zhaw.prog2.fxmlcalculator; | |
import javafx.fxml.FXML; | |
import javafx.fxml.FXMLLoader; | |
import javafx.scene.Parent; | |
import javafx.scene.Scene; | |
import javafx.scene.control.*; | |
import javafx.stage.Stage; | |
import java.io.IOException; | |
/** | |
* Controller for the MainWindow. One controller per mask (or FXML file) | |
* Contains everything the controller has to reach in the view (controls) | |
* and all methods the view calls based on events. | |
* @author | |
* @version 1.0 | |
*/ | |
public class MainWindowController { | |
@FXML private MenuBar menuBar; | |
@FXML private CheckMenuItem checkmenuitem_clear_initial_amount; | |
@FXML private CheckMenuItem checkmenuitem_return_in_percent; | |
@FXML private CheckMenuItem checkmenuitem_annual_cost; | |
@FXML private CheckMenuItem checkmenuitem_number_years; | |
@FXML private MenuItem menuitem_clear_values; | |
@FXML private MenuItem menuitem_clear_results; | |
@FXML private MenuItem menuitem_show_help; | |
@FXML private TextArea textarea_results; | |
@FXML private TextField textfield_initial_amount; | |
@FXML private TextField textfield_return_rate; | |
@FXML private TextField textfield_annual_cost; | |
@FXML private TextField textfield_number_of_years; | |
@FXML private Button button_calculate; | |
@FXML private Button button_close; | |
@FXML private Button button_open_results; | |
private ValueHandler valueHandler; | |
/** | |
* Constructor | |
*/ | |
public MainWindowController() { | |
valueHandler = new ValueHandler(); | |
} | |
// called by the FXML loader after the labels declared above are injected: | |
public void initialize() { | |
button_close.setOnAction((event) -> { | |
Stage stage = (Stage) button_close.getScene().getWindow(); | |
stage.close(); | |
}); | |
button_calculate.setOnAction((event) -> { | |
String initialAmount = textfield_initial_amount.getText(); | |
String returnRate = textfield_return_rate.getText(); | |
String annualCost = textfield_annual_cost.getText(); | |
String numberOfYears = textfield_number_of_years.getText(); | |
valueHandler.checkAndCalculateResult(initialAmount, returnRate, annualCost, numberOfYears); | |
if (valueHandler.areValuesOk()) { | |
textarea_results.setStyle("-fx-border-color: green; -fx-focus-color: green"); | |
textarea_results.setText(valueHandler.getResultBound()); | |
} else { | |
textarea_results.setStyle("-fx-border-color: red; -fx-focus-color: red"); | |
textarea_results.setText(valueHandler.getResultBound()); | |
} | |
}); | |
// menu bar connections | |
menuitem_clear_values.setOnAction((event) -> { | |
if (checkmenuitem_clear_initial_amount.isSelected()) { | |
textfield_initial_amount.clear(); | |
} | |
if (checkmenuitem_return_in_percent.isSelected()) { | |
textfield_return_rate.clear(); | |
} | |
if (checkmenuitem_annual_cost.isSelected()) { | |
textfield_annual_cost.clear(); | |
} | |
if (checkmenuitem_number_years.isSelected()) { | |
textfield_number_of_years.clear(); | |
} | |
}); | |
menuitem_clear_results.setOnAction(event -> textarea_results.clear()); | |
menuitem_show_help.setOnAction(event -> { | |
textarea_results.setStyle("-fx-border-color: blue; -fx-focus-color:blue"); | |
textarea_results.setText(valueHandler.getHelpText()); | |
}); | |
valueHandler.resultBoundProperty().addListener((observable, oldValue, newValue) -> { | |
}); | |
button_open_results.setOnAction(event -> { | |
try { | |
FXMLLoader loader = new FXMLLoader(getClass().getResource("ResultWindow.fxml")); | |
Parent root = loader.load(); | |
Scene scene = new Scene(root); | |
Stage stageOfNewWindow = new Stage(); | |
stageOfNewWindow.setTitle("Results"); | |
stageOfNewWindow.setScene(scene); | |
stageOfNewWindow.setMinWidth(410); | |
stageOfNewWindow.setMinHeight(280); | |
// stageOfNewWindow.initOwner(textarea_results.getScene().getWindow()); | |
// stageOfNewWindow.initModality(Modality.WINDOW_MODAL); | |
((ResultWindowController) loader.getController()).setValueHandler(valueHandler); | |
// we need to fire the calculate button to update the text on the new window | |
button_calculate.fire(); | |
stageOfNewWindow.show(); | |
} catch (IOException e) { | |
throw new RuntimeException(e); | |
} | |
}); | |
} // initialize | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<?import java.lang.*?> | |
<?import javafx.geometry.*?> | |
<?import javafx.scene.control.*?> | |
<?import javafx.scene.layout.*?> | |
<?import javafx.scene.text.*?> | |
<?import javafx.geometry.Insets?> | |
<?import javafx.scene.control.Button?> | |
<?import javafx.scene.control.Label?> | |
<?import javafx.scene.control.TextArea?> | |
<?import javafx.scene.input.KeyCodeCombination?> | |
<?import javafx.scene.layout.BorderPane?> | |
<?import javafx.scene.layout.ColumnConstraints?> | |
<?import javafx.scene.layout.GridPane?> | |
<?import javafx.scene.layout.HBox?> | |
<?import javafx.scene.layout.RowConstraints?> | |
<?import javafx.scene.layout.VBox?> | |
<?import javafx.scene.text.Font?> | |
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="250.0" minWidth="400.0" prefHeight="250.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.prog2.fxmlcalculator.ResultWindowController"> | |
<center> | |
<VBox minWidth="300.0" BorderPane.alignment="TOP_CENTER"> | |
<padding> | |
<Insets left="10.0" right="10.0"/> | |
</padding> | |
<VBox spacing="5.0" VBox.vgrow="ALWAYS"> | |
<VBox.margin> | |
<Insets top="10.0"/> | |
</VBox.margin> | |
<Label text="Results"> | |
<font> | |
<Font name="System Bold" size="12.0"/> | |
</font> | |
</Label> | |
<TextArea fx:id="textarea_results" editable="false" minHeight="100.0" VBox.vgrow="ALWAYS"/> | |
</VBox> | |
</VBox> | |
</center> | |
<bottom> | |
<HBox alignment="BOTTOM_RIGHT" BorderPane.alignment="CENTER"> | |
<BorderPane.margin> | |
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/> | |
</BorderPane.margin> | |
<Button fx:id="closeForm" mnemonicParsing="false" onMouseClicked="#closeWindow" text="Close"> | |
<HBox.margin> | |
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/> | |
</HBox.margin> | |
</Button> | |
</HBox> | |
</bottom> | |
</BorderPane> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ch.zhaw.prog2.fxmlcalculator; | |
import javafx.fxml.FXML; | |
import javafx.scene.control.TextArea; | |
import javafx.stage.Stage; | |
/** | |
* Controller for the MainWindow. One controller per mask (or FXML file) | |
* Contains everything the controller has to reach in the view (controls) | |
* and all methods the view calls based on events. | |
* @author | |
* @version 1.0 | |
*/ | |
public class ResultWindowController { | |
@FXML private TextArea textarea_results; | |
@FXML | |
private void closeWindow() { | |
Stage stage = (Stage) textarea_results.getScene().getWindow(); | |
stage.close(); | |
} | |
public void setValueHandler(ValueHandler valueHandler) { | |
valueHandler.resultBoundProperty().addListener((observable, oldValue, newValue) -> { | |
if (valueHandler.areValuesOk()) { | |
textarea_results.setStyle("-fx-border-color: green; -fx-focus-color: green"); | |
textarea_results.setText(valueHandler.getResultBound()); | |
textarea_results.layout(); | |
} else { | |
textarea_results.setStyle("-fx-border-color: red; -fx-focus-color: red"); | |
textarea_results.setText(valueHandler.getResultBound()); | |
} | |
}); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ch.zhaw.prog2.fxmlcalculator; | |
import javafx.beans.property.SimpleStringProperty; | |
import javafx.beans.property.StringProperty; | |
/** | |
* Handles the values from the input form. Offers the {@link resultBound} StringProperty to listen from | |
* a GUI (bind to a field in the GUI) | |
* @author bles | |
* @version 1.1 | |
* MODEL | |
*/ | |
public class ValueHandler { | |
private double initialAmount; | |
private double returnInPercent; | |
private double annualCost; | |
private int numberOfYears; | |
private boolean valuesOk = false; | |
// Solution with bound properties | |
private final StringProperty resultBound = new SimpleStringProperty(); | |
public ValueHandler() { | |
} | |
/** | |
* Check the input values are valid (can be improved) | |
* If not ok, fill error message to the results and return false | |
* If ok, set the date fields and return true | |
*/ | |
private String checkValues(String initialAmount, String returnInPercent, String annualCost, String numberOfYears) { | |
StringBuilder sb = new StringBuilder(); | |
valuesOk = true; | |
if ("".equals(initialAmount) || Double.parseDouble(initialAmount)<=0) { | |
sb.append("Please specify a positive initial amount!\n"); | |
valuesOk = false; | |
} else { | |
this.initialAmount = Double.parseDouble(initialAmount); | |
} | |
if ("".equals(returnInPercent)) { | |
sb.append("Please specify the annual return rate in %!\n"); | |
valuesOk = false; | |
} else { | |
this.returnInPercent = Double.parseDouble(returnInPercent)/100; | |
} | |
if ("".equals(annualCost) || Double.parseDouble(annualCost)<0) { | |
sb.append("Please specify the annual cost!\n"); | |
valuesOk = false; | |
} else { | |
this.annualCost = Double.parseDouble(annualCost); | |
} | |
if ("".equals(numberOfYears) || | |
Double.parseDouble(numberOfYears) < 1 || | |
Double.parseDouble(numberOfYears) > 99 || | |
Math.round(Double.parseDouble(numberOfYears))!=Double.parseDouble(numberOfYears)) { | |
sb.append("Please enter a time period in years!"); | |
valuesOk = false; | |
} else { | |
this.numberOfYears = Integer.parseInt(numberOfYears); | |
} | |
return sb.toString(); | |
} | |
/** | |
* Calculates the result | |
* @return the result as a String | |
*/ | |
private String calculateResult() { | |
StringBuilder resultSB = new StringBuilder(); | |
double val = initialAmount; | |
for(int i = 1; i <= numberOfYears; i++) { | |
resultSB.append("After "); | |
resultSB.append(i).append(" year(s): "); | |
val = val * (1 + returnInPercent) - annualCost; | |
resultSB.append(Math.round(val)).append("\n"); | |
} | |
return resultSB.toString(); | |
} | |
/** | |
* Result String can be "", if no calculation or check is done | |
* @return String with the result of the value checking or the calculation | |
*/ | |
public String getResultBound() { | |
return resultBound.get(); | |
} | |
/** | |
* Set the result to the string in the parameter | |
* @param infoText | |
*/ | |
public void setResultBound(String infoText) { | |
resultBound.set(infoText); | |
} | |
/** | |
* If the values checked by {@link checkValues} are ok, the return is true | |
* @return true, if ok | |
*/ | |
public boolean areValuesOk() { | |
return valuesOk; | |
} | |
// Solution with bound properties | |
/** | |
* The property to bind | |
* @return | |
*/ | |
public StringProperty resultBoundProperty() { | |
return resultBound; | |
} | |
/** | |
* Checks and calculates the result. All values as String (from the Text-Fields) | |
* If the check fails, an error message is set to the bound result property | |
* @param initialAmount | |
* @param returnInPercent | |
* @param annualCost | |
* @param numberOfYears | |
*/ | |
public void checkAndCalculateResult(String initialAmount, String returnInPercent, String annualCost, String numberOfYears) { | |
setResultBound(checkValues(initialAmount, returnInPercent, annualCost, numberOfYears)); | |
if(valuesOk) { | |
setResultBound(calculateResult()); | |
} | |
} | |
public String getHelpText() { | |
return "Enter valid values to\n" + | |
"- Initial amount (>0)\n" + | |
"- Return in % (can be +/- or 0)\n" + | |
"- Annual costs (>0)\n" + | |
"- Number of years (>0)\n" + | |
"\n" + | |
"Calculate display the annual balance development!"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment