Javafx: Binding font size to container - javafx

I am currently working on my final year project which is to create a Sudoku game/solver. The problem I have is that I am cannot find a method of resizing font size to that of its container when using a scene framework.
I would like to have the font size of a label change to the corresponding size of the gridpane it is within. I however am finding it hard to bind the properties I need such as 'widthProperty' and 'heightProperty' to that of 'Font.font(size)'
The difference of this question to other binding questions, is that my scene framework interferes with putting the binding for controls in the initialize method of a controller. I cannot do this as all of my controllers are initialized on start up not when they are shown to the scene
Here is all my code:
Main.java
package Controller;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
public static String mainMenu = "Main Menu";
public static String mainMenuFXML = "/FXML/MainMenu.fxml";
public static String chooseLevel = "Level Selection";
public static String chooseLevelFXML = "/FXML/ChooseLevel.fxml";
//Global Variable to be accessed across all classes
//To be used to determine which scenes are loaded in the HashMap and also which scene has been set
public static SceneFramework mainController = new SceneFramework();
#Override
public void start(Stage primaryStage) throws Exception{
//Only the main menu scene is needed to be loaded at the start
mainController.loadScene(Main.mainMenu, Main.mainMenuFXML);
mainController.setScene(Main.mainMenu);
StackPane root = new StackPane();
root.getChildren().addAll(mainController);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
SceneFramework.java
package Controller;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.layout.StackPane;
import java.util.HashMap;
public class SceneFramework extends StackPane{
//Constructor for the class
public SceneFramework(){
//The keyword super, overrides methods from the superclass
super();
}
//This HashMap is used to hold the screens(scenes) to be used within the application
protected HashMap<String, Node> scenes = new HashMap<>();
//Adds the selected scene to the HashMap
public void addScene(String title, Node scene) {
scenes.put(title, scene);
}
//Returns the Node with the specified title for use within application
public Node getScene(String title) {
return scenes.get(title);
}
//Removes the selected scene from the framework
public boolean unloadScene(String title){
if(scenes.remove(title) == null){
System.out.println("Scene cannot be located or it doesn't exist");
return false;
} else{
return true;
}
}
public boolean loadScene(String title, String resource){
//encase code segment in try for exception handling,
// as resources are required to be found and then loaded into memory
try{
//Load FXML File
FXMLLoader loadedFXMLFile = new FXMLLoader(getClass().getResource(resource));
//Get Parent of scene
Parent loadScene = loadedFXMLFile.load();
//Get the Controller class of the parent
SetSceneParent sceneController = (loadedFXMLFile.getController());
//Method of making sure every scene knows who it's parent is
sceneController.setSceneParent(this);
//Add scene to HashMap
addScene(title, loadScene);
return true;
}catch (Exception e){
//If FXML resource can't be loaded then generate this
System.out.println("Could't load FXML file");
return false;
}
}
//Method for showing scenes
//If one scenes if wanting to be shown then it is added to the root
//If multiple scenes are wanting to be loaded then the first scene is removed and the new scene is then displayed
public boolean setScene(final String title){
//Check to see if scene can be found
if(scenes.get(title) != null) {
if(!getChildren().isEmpty()){
getChildren().remove(0);
getChildren().add(0 ,scenes.get(title));
}else{
getChildren().add(scenes.get(title));
}
return true;
} else{
System.out.println("Scene not located!!!");
return false;
}
}
}
SetSceneParent.java
package Controller;
import Controller.SceneFramework;
public interface SetSceneParent {
void setSceneParent(SceneFramework sceneParent);
}
MainMenuController.java
package Controller;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import java.net.URL;
import java.util.ResourceBundle;
public class MainMenuController implements Initializable, SetSceneParent {
#FXML
public Button playButton, optionsButton, quitButton;
#Override
public void initialize(URL location, ResourceBundle resources) {
SelectionStatus.initialize();
}
#Override
public void setSceneParent(SceneFramework sceneParent) {
//Sets the parent of the scene by using the global variable of the class SceneFramework
Main.mainController = sceneParent;
}
public void handlePlayButtonAction(){
//On clicking of the play button
//The user is taken to the level difficulty scene
Main.mainController.loadScene(Main.chooseLevel, Main.chooseLevelFXML);
Main.mainController.setScene(Main.chooseLevel);
Main.mainController.unloadScene(Main.mainMenu);
}
}
MainMenu.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="480.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller.MainMenuController">
<center>
<HBox>
<children>
<VBox alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" BorderPane.alignment="TOP_CENTER" HBox.hgrow="ALWAYS">
<children>
<Label alignment="TOP_CENTER" maxHeight="120.0" prefHeight="60.0" text="Sudoku Solver" textAlignment="CENTER" underline="true" wrapText="true" VBox.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="48.0" />
</font>
<VBox.margin>
<Insets right="10.0" />
</VBox.margin>
</Label>
<Button fx:id="playButton" maxHeight="175.0" maxWidth="1400.0" mnemonicParsing="false" onAction="#handlePlayButtonAction" prefHeight="60.0" prefWidth="300.0" text="Play" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets />
</VBox.margin>
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Region maxHeight="80.0" prefHeight="0.0" VBox.vgrow="ALWAYS" />
<Button fx:id="optionsButton" maxHeight="175.0" maxWidth="1400.0" mnemonicParsing="false" prefHeight="60.0" prefWidth="300.0" text="Options" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets />
</VBox.margin>
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Region maxHeight="80.0" prefHeight="0.0" VBox.vgrow="ALWAYS" />
<Button fx:id="quitButton" maxHeight="175.0" maxWidth="1400.0" mnemonicParsing="false" prefHeight="60.0" prefWidth="300.0" text="Quit" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets />
</VBox.margin>
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
</children>
</VBox>
</children>
</HBox>
</center>
<left>
<HBox BorderPane.alignment="CENTER">
<children>
<Region maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefWidth="100.0" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</left>
<right>
<HBox BorderPane.alignment="CENTER">
<children>
<Region maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefWidth="100.0" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</right>
<bottom>
<VBox BorderPane.alignment="CENTER">
<children>
<Region prefHeight="60.0" VBox.vgrow="ALWAYS" />
</children>
</VBox>
</bottom>
</BorderPane>
ChooseLevelController.java
package Controller;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import java.net.URL;
import java.util.ResourceBundle;
public class ChooseLevelController implements Initializable, SetSceneParent {
#FXML
public Label lblLevelSelection, lblLevel1, lblLevel2, lblLevel3, lblLevel4, lblLevel5, lblLevel6, lblLevel7, lblLevel8, lblLevel9, lblLevel10; // Value injected by FXMLLoader
public Button backButton;
public GridPane gridPaneCenter;
#Override
public void initialize(URL location, ResourceBundle resources) {
//Assert code is to be used in debugging making sure references to files and their elements are correct
assert lblLevel1 != null : "fx:id=\"lblLevel1\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel2 != null : "fx:id=\"lblLevel2\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel3 != null : "fx:id=\"lblLevel3\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel4!= null : "fx:id=\"lblLevel4\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel5 != null : "fx:id=\"lblLevel5\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel6 != null : "fx:id=\"lblLevel6\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel7 != null : "fx:id=\"lblLevel7\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel8 != null : "fx:id=\"lblLevel8\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel9 != null : "fx:id=\"lblLevel9\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel10 != null : "fx:id=\"lblLevel10\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
}
#Override
public void setSceneParent(SceneFramework screenParent) {
//Sets the parent of the scene by using the global variable of the class SceneFramework
Main.mainController = screenParent;
}
//Logic code
#FXML
public void mouseClickedLevelLabel() {
//Load the play screen when any Label is pressed
lblLevel1.setOnMouseClicked(e -> handleLabelClick(1));
lblLevel2.setOnMouseClicked(e -> handleLabelClick(2));
lblLevel3.setOnMouseClicked(e -> handleLabelClick(3));
lblLevel4.setOnMouseClicked(e -> handleLabelClick(4));
lblLevel5.setOnMouseClicked(e -> handleLabelClick(5));
lblLevel6.setOnMouseClicked(e -> handleLabelClick(6));
lblLevel7.setOnMouseClicked(e -> handleLabelClick(7));
lblLevel8.setOnMouseClicked(e -> handleLabelClick(8));
lblLevel9.setOnMouseClicked(e -> handleLabelClick(9));
lblLevel10.setOnMouseClicked(e -> handleLabelClick(10));
}
#FXML
public void handleBackButtonAction() {
//On clicking of the back button
//The user is taken to the level difficulty scene
Main.mainController.loadScene(Main.mainMenu, Main.mainMenuFXML);
Main.mainController.setScene(Main.mainMenu);
Main.mainController.unloadScene(Main.chooseLevel);
}
}
ChooseLevel.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller.ChooseLevelController">
<center>
<VBox alignment="CENTER" BorderPane.alignment="CENTER">
<children>
<GridPane fx:id="gridPaneCenter" alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1500.0" prefHeight="242.0" prefWidth="475.0" BorderPane.alignment="CENTER" VBox.vgrow="ALWAYS">
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="10.0" prefHeight="137.0" vgrow="ALWAYS" />
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="10.0" prefHeight="138.0" vgrow="ALWAYS" />
</rowConstraints>
<children>
<Label fx:id="lblLevel1" onMousePressed="#mouseClickedLevelLabel" text="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel2" onMouseClicked="#mouseClickedLevelLabel" onMousePressed="#mouseClickedLevelLabel" text="2" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel3" onMousePressed="#mouseClickedLevelLabel" text="3" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel4" onMousePressed="#mouseClickedLevelLabel" text="4" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel5" onMousePressed="#mouseClickedLevelLabel" text="5" GridPane.columnIndex="4" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel6" onMouseClicked="#mouseClickedLevelLabel" onMousePressed="#mouseClickedLevelLabel" text="6" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel7" onMousePressed="#mouseClickedLevelLabel" text="7" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel8" onMousePressed="#mouseClickedLevelLabel" text="8" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel9" onMousePressed="#mouseClickedLevelLabel" text="9" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel10" onMousePressed="#mouseClickedLevelLabel" text="10" GridPane.columnIndex="4" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
</children>
</GridPane>
</children>
</VBox>
</center>
<top>
<GridPane fx:id="gridPaneTop">
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" maxWidth="207.0" minWidth="10.0" prefWidth="20.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="207.0" minWidth="10.0" prefWidth="58.0" />
<ColumnConstraints hgrow="ALWAYS" maxWidth="207.0" minWidth="10.0" prefWidth="105.0" />
<ColumnConstraints hgrow="ALWAYS" maxWidth="451.0" minWidth="10.0" prefWidth="418.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button fx:id="backButton" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleBackButtonAction" prefHeight="30.0" prefWidth="0.0" text="Back" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.valignment="CENTER" />
<Separator prefHeight="63.0" prefWidth="73.0" visible="false" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.valignment="CENTER" GridPane.vgrow="ALWAYS" />
<Label fx:id="lblLevelSelection" text="Level Selection" underline="true" GridPane.columnIndex="3">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Separator prefHeight="63.0" prefWidth="73.0" visible="false" />
</children>
</GridPane>
</top>
<bottom>
<Region prefHeight="36.0" prefWidth="600.0" BorderPane.alignment="CENTER" />
</bottom>
<left>
<HBox>
<children>
<Region maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="50.0" BorderPane.alignment="CENTER" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</left>
<right>
<HBox>
<children>
<Region maxWidth="1.7976931348623157E308" prefHeight="300.0" prefWidth="50.0" BorderPane.alignment="CENTER" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</right>
</BorderPane>

Ok your code does not compile AGAIN. So I'll just post a minimal example:
App.java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class App extends Application {
#Override
public void start(Stage primaryStage) {
View view = new View();
Scene scene = new Scene(view, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
View.java
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
public class View extends AnchorPane {
public View() {
GridPane gridPane = new GridPane();
ColumnConstraints column = new ColumnConstraints();
column.setPercentWidth(33.33);
column.setHalignment(HPos.CENTER);
gridPane.getColumnConstraints().addAll(column, column, column);
RowConstraints row = new RowConstraints();
row.setPercentHeight(33.33);
row.setValignment(VPos.CENTER);
gridPane.getRowConstraints().addAll(row, row, row);
gridPane.setGridLinesVisible(true);
AnchorPane.setTopAnchor(gridPane, 0.0);
AnchorPane.setBottomAnchor(gridPane, 0.0);
AnchorPane.setLeftAnchor(gridPane, 0.0);
AnchorPane.setRightAnchor(gridPane, 0.0);
for ( int i = 0 ; i < 9; i++ ) {
gridPane.add(new Label(i+1+""), i%3, i/3, 1, 1);
}
this.widthProperty().addListener( event -> {
this.setStyle("-fx-font-size: " + this.getWidth()/10);
});
this.getChildren().add(gridPane);
}
}
This is EXACTLY what i proposed on your other question...
Edit:
To change the font of the exact element you could go about it like this:
this.widthProperty().addListener( event -> {
ObservableList<Node> labelList = gridPane.getChildren();
for ( int i = 0; i < labelList.size(); i++ ) {
//labelList.get(i).setStyle("-fx-font-size: " + this.getWidth()/10);
if ( labelList.get(i).getClass().equals(Label.class) ) {
Label.class.cast(labelList.get(i)).setFont(Font.font(this.getWidth()/10));
}
}
});
Edit2:
To have the font scale with the height AND the width you could use a method such as this:
private void changeFontSize(List<Node> labelList) {
Double newFontSizeDouble = Math.hypot(this.getWidth(), this.getHeight())/10;
int newFontSizeInt = newFontSizeDouble.intValue();
for ( int i = 0; i < labelList.size(); i++ ) {
if ( labelList.get(i).getClass().equals(Label.class) ) {
Label.class.cast(labelList.get(i)).setFont(Font.font(newFontSizeInt));
}
}
}
And call it like this:
this.widthProperty().addListener( event -> changeFontSize(gridPane.getChildren()));
this.heightProperty().addListener( event -> changeFontSize(gridPane.getChildren()));
Edit3:
You can also bind them using property bindings. There's a good tutorial on youtube here:
https://www.youtube.com/watch?v=s8GomyEOA8w&index=29&list=PL6gx4Cwl9DGBzfXLWLSYVy8EbTdpGbUIG

Related

Java runtime error as well as load exception error

Hi I am getting this error when trying to run my fxml file created in oracle scene builder the fxml file is labelled with the proper names for each of the buttons as well as the controller class being properly labelled, my control code for the in question error looks like this
package prog24178;
import javafx.collections.FXCollections;
import java.util.ArrayList;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.Alert.AlertType;
import java.io.File;
import java.io.PrintWriter;
import java.util.Scanner;
import javafx.scene.control.ListView;
public class DataBaseController implements Config{
#FXML TextField txt1, txt2, txt3, txt4;
#FXML Button b1, b2, b3, b4, b5;
#FXML ListView<String> list;
#FXML private ArrayList<String> stringItems = new ArrayList<String>();
#FXML private ArrayList<Item> items = new ArrayList<Item>();
#FXML
public void add(ActionEvent e) {
int id = Integer.parseInt(txt1.getText());
String item = txt2.getText();
int quantity = Integer.parseInt(txt3.getText());
double price = Double.parseDouble(txt4.getText());
items.add(new Item(id, item, quantity, price));
list.getItems().clear();
stringItems.clear();
for(Item item1 : items) stringItems.add(item1.toString());
ObservableList<String> items = FXCollections.observableArrayList(stringItems);
list.setItems(items);
}
#FXML
public void load(ActionEvent e) {
items.clear();
stringItems.clear();
list.getItems().clear();
File f = new File(FILE);
try {
if(!f.exists()) f.createNewFile();
Scanner lines = new Scanner(f);
if(!lines.hasNextLine()) {
Alert alert = new Alert(AlertType.INFORMATION, "data file is empty\nenter car and click the save button");
alert.showAndWait();
}
else {
while(lines.hasNextLine()) {
Scanner line = new Scanner(lines.nextLine());
line.useDelimiter(":\\s*");
items.add(new Item(line.nextInt(), line.next(), line.nextInt(), line.nextDouble()));
line.close();
}
}
lines.close();
for(Item item1 : items)
list.getItems().add(item1.toString());
//stringCars.add(car.toString());
//ObservableList<String> items = FXCollections.observableArrayList(stringCars);
//list.setItems(items);
} catch (Exception e1) {
e1.printStackTrace();
}
}
#FXML
public void save(ActionEvent e) {
File f = new File(FILE);
try {
if(!f.exists()) f.createNewFile();
PrintWriter pw = new PrintWriter(f);
for(Item c : items)
pw.printf("%s:%s:%s:%d:%b\n",
c.getID(), c.getItem(), c.getQuantity(), c.getPrice());
pw.close();
} catch (Exception e1) {
e1.printStackTrace();
}
Alert alert = new Alert(AlertType.INFORMATION, "data is saved in a file\nyou can close the \napplication now");
alert.showAndWait();
}
#FXML
public void modify(ActionEvent e) {
}
#FXML
public void remove(ActionEvent e) {
}
}
the RunApp class
package prog24178;
import java.net.URL;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class RunApp extends javafx.application.Application implements Config{
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage ps) throws Exception {
URL res = this.getClass().getResource("control.fxml");
Parent scene = FXMLLoader.load(res);
Scene ourscene = new Scene(scene);
ps.setScene(ourscene);
ps.setTitle("Items Database");
ps.show();
}
}
the implemented config interface
as well as the full error message
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$1(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:748)
Caused by: javafx.fxml.LoadException: Error resolving onAction='add', either the event handler is not in the Namespace or there is an error in the script.
/C:/Users/Canada%20Computers/workspace/Assign6/bin/prog24178/control.fxml:44
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2597)
at javafx.fxml.FXMLLoader.access$100(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$Element.processEventHandlerAttributes(FXMLLoader.java:610)
at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:770)
at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2823)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2532)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
at prog24178.RunApp.start(RunApp.java:17)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:186)
... 1 more
Exception running application prog24178.RunApp
FXML code
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="384.0" prefWidth="664.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="prog24178.RunApp">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="130.0" minWidth="10.0" prefWidth="51.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="276.0" minWidth="10.0" prefWidth="34.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="253.0" minWidth="0.0" prefWidth="39.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="307.0" minWidth="10.0" prefWidth="203.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="446.0" minWidth="10.0" prefWidth="66.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="446.0" minWidth="10.0" prefWidth="75.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="446.0" minWidth="10.0" prefWidth="51.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="446.0" minWidth="10.0" prefWidth="148.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints />
<RowConstraints maxHeight="48.0" minHeight="10.0" prefHeight="48.0" />
<RowConstraints maxHeight="48.0" minHeight="0.0" prefHeight="40.0" />
<RowConstraints maxHeight="44.0" minHeight="8.0" prefHeight="32.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="274.0" minHeight="10.0" prefHeight="32.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="274.0" minHeight="10.0" prefHeight="201.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="123.0" minHeight="10.0" prefHeight="31.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label alignment="CENTER_RIGHT" text="ID:" GridPane.halignment="CENTER" GridPane.rowIndex="2" />
<TextField fx:id="txt1" prefHeight="25.0" prefWidth="46.0" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="Item:" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="2" />
<TextField fx:id="txt2" GridPane.columnIndex="3" GridPane.rowIndex="2" />
<Label prefHeight="17.0" prefWidth="57.0" text="Quanitity:" GridPane.columnIndex="4" GridPane.halignment="CENTER" GridPane.rowIndex="2" />
<TextField fx:id="txt3" GridPane.columnIndex="5" GridPane.rowIndex="2" />
<Label text="Price:" GridPane.columnIndex="6" GridPane.halignment="CENTER" GridPane.rowIndex="2" />
<TextField fx:id="txt4" GridPane.columnIndex="7" GridPane.rowIndex="2">
<GridPane.margin>
<Insets />
</GridPane.margin>
</TextField>
<HBox prefHeight="29.0" prefWidth="516.0" spacing="10.0" GridPane.columnIndex="3" GridPane.columnSpan="2147483647" GridPane.rowIndex="3">
<children>
<Button fx:id="b1" mnemonicParsing="false" onAction="add" text="Add Item" />
<Button fx:id="b2" mnemonicParsing="false" onAction="#modify" text="Modify Item" />
<Button fx:id="b3" mnemonicParsing="false" onAction="#remove" prefHeight="25.0" prefWidth="107.0" text="Remove Item" />
</children>
<GridPane.margin>
<Insets top="10.0" />
</GridPane.margin>
</HBox>
<HBox prefHeight="100.0" prefWidth="200.0" GridPane.columnSpan="2147483647" GridPane.rowIndex="5">
<children>
<ListView fx:id="list" prefHeight="201.0" prefWidth="627.0">
<padding>
<Insets left="20.0" right="10.0" />
</padding>
</ListView>
</children>
</HBox>
<Label text="Items:" GridPane.halignment="CENTER" GridPane.rowIndex="4" />
<HBox prefHeight="100.0" prefWidth="200.0" spacing="10.0" GridPane.columnIndex="3" GridPane.columnSpan="2147483647" GridPane.rowIndex="6">
<children>
<Button fx:id="b4" mnemonicParsing="false" onAction="#load" text="Load Data From File" />
<Button fx:id="b5" mnemonicParsing="false" onAction="#save" text="Save Data To File" />
</children>
</HBox>
<HBox prefHeight="100.0" prefWidth="200.0" GridPane.columnIndex="3" GridPane.columnSpan="2147483647" GridPane.rowIndex="1">
<children>
<Label alignment="CENTER" prefHeight="48.0" prefWidth="318.0" text="Database of Items">
<font>
<Font size="26.0" />
</font>
</Label>
</children>
</HBox>
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
</GridPane>

How to create Javafx save, read information from text file and letting user to edit their information

How to create JavaFx RegisterGUI save user information(Username,password,name,email,phone number,address) and load into UserProfile GUI that allow the user to edit their profile information after login with their username and password? Hope you guys can help me with the problems.
UserGUI:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Text?>
<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.GUIButton">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button id="btnEdit" fx:id="btnEdit" mnemonicParsing="false" onAction="#setOnAction" text="Edit Profile" GridPane.columnIndex="1" GridPane.rowIndex="9" />
<Button id="btnSave" fx:id="btnSave" mnemonicParsing="false" onAction="#setOnAction" prefHeight="26.0" prefWidth="73.0" text="Save" GridPane.columnIndex="2" GridPane.rowIndex="9" />
<Button id="btnCancel" fx:id="btnCancel" mnemonicParsing="false" onAction="#setOnAction" prefHeight="26.0" prefWidth="66.0" text="Cancel" GridPane.columnIndex="3" GridPane.rowIndex="9" />
<Text id="txtName" strokeType="OUTSIDE" strokeWidth="0.0" text="Name" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Text id="txtPhoneNumber" strokeType="OUTSIDE" strokeWidth="0.0" text="Phone Number" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Text id="txtEmail" strokeType="OUTSIDE" strokeWidth="0.0" text="Email" GridPane.columnIndex="1" GridPane.rowIndex="5" />
<Text id="txtAddress" strokeType="OUTSIDE" strokeWidth="0.0" text="Address" GridPane.columnIndex="1" GridPane.rowIndex="7" />
<TextField id="txtfName" onAction="#setOnAction" prefHeight="26.0" prefWidth="203.0" GridPane.columnIndex="2" GridPane.rowIndex="1" />
<TextField id="txtfPhoneNumber" onAction="#setOnAction" GridPane.columnIndex="2" GridPane.rowIndex="3" />
<TextField id="txtfEmail" onAction="#setOnAction" GridPane.columnIndex="2" GridPane.rowIndex="5" />
<TextArea id="txtaAddress" onDragDetected="#setOnAction" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="7" />
<ImageView id="imgUser" fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="4" GridPane.rowIndex="2" />
</children>
</GridPane>
RegisterGUI :
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Text?>
<GridPane id="RegisterGUI" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/10.0.1" fx:controller="application.RegisterButton">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="193.5999755859375" minWidth="10.0" prefWidth="151.20003662109374" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="193.5999755859375" minWidth="10.0" prefWidth="151.20003662109374" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="447.9999633789063" minWidth="10.0" prefWidth="447.9999633789063" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Email" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Username" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Name" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="IC Number" GridPane.columnIndex="1" GridPane.rowIndex="5" />
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Phone Number" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Address" GridPane.columnIndex="1" GridPane.rowIndex="7" />
<TextField id="txtfEmail" fx:id="txtfEmail" GridPane.columnIndex="2" GridPane.rowIndex="1" />
<TextField id="txtfUsername" fx:id="txtfUsername" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<TextField id="txtfName" fx:id="txtfName" GridPane.columnIndex="2" GridPane.rowIndex="4" />
<TextField id="txtfIC" fx:id="txtfIC" GridPane.columnIndex="2" GridPane.rowIndex="5" />
<TextField id="txtfPhone" fx:id="txtfPhone" GridPane.columnIndex="2" GridPane.rowIndex="6" />
<TextArea id="txtaAddress" fx:id="txtaAddress" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="7" />
<Button id="btnRegister" fx:id="btnRegister" mnemonicParsing="false" onAction="#OnRegister" text="Register" GridPane.columnIndex="2" GridPane.rowIndex="9" />
<Button id="btnExit" fx:id="btnExit" mnemonicParsing="false" onAction="#OnExit" prefHeight="26.0" prefWidth="56.0" text="Exit" GridPane.columnIndex="1" GridPane.rowIndex="9" />
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Password" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<TextField id="txtfPassword" fx:id="txtfPassword" GridPane.columnIndex="2" GridPane.rowIndex="3" />
</children>
</GridPane>
Ok build a small login, Signup, and Edit app for you, You can modify it as u like
So we have 4 class files. and 2 FXML files and Textfile
Luncher.java
package loginApplication;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Luncher extends Application{
public static Stage stage;
#Override
public void start(Stage primaryStage) throws Exception {
stage = primaryStage;
Parent root = FXMLLoader.load(getClass().getResource("Login.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
LoginController.java
package loginApplication;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
public class LoginController
{
#FXML
private TextField email_textfield;
#FXML
private PasswordField password_textfield;
#FXML
private Label error_lab;
#FXML
public void signupButton(ActionEvent event) {
openWindow();
}
#FXML
public void loginButton(ActionEvent event) throws IOException
{
//Path to text file
Path path = Paths.get("TextFiles/data.txt");
//Counts number of line in text file
long count = Files.lines(path).count();
/// read each line
for (int i = 0; i < count; i++)
{
String line = Files.readAllLines(path).get(i);
if(!line.trim().equals(""))
{
//According to format Name, Email, Password, Age, Gender
String[] profile = line.split(",");
String name = profile[0];
String email = profile[1];
String password = profile[2];
String age = profile[3];
String gender = profile[4];
String contact = profile[5];
//Email Matched!
if(email.trim().equals(email_textfield.getText()))
{ //Note trim() method remove space from front and behind of string if there is any
//Now checking if password match
if(password.trim().equals(password_textfield.getText()))
{
Alert msg = new Alert(AlertType.CONFIRMATION);
msg.setTitle(email_textfield.getText());
msg.setContentText("Email and password matched");
msg.showAndWait();
//Store values
Storage.setName(name);
Storage.setEmail(email);
Storage.setAge(age);
Storage.setGender(gender);
Storage.setContact(contact);
Storage.setPassword(password);
//open login window
openWindow();
break; //Email match and pass match, Close loop
}
}
}
}
if(Storage.getEmail() == null) {
System.out.println("No such email");
Alert msg = new Alert(AlertType.ERROR);
msg.setTitle(email_textfield.getText());
msg.setContentText("No such Email : " +email_textfield.getText());
msg.showAndWait();
} else if (Storage.getPassword() == null){
System.out.println("No such email");
Alert msg = new Alert(AlertType.ERROR);
msg.setTitle(email_textfield.getText());
msg.setContentText("Wrong password");
msg.showAndWait();
}
}
private void openWindow()
{
System.out.println("Profile open");
try {
Parent root = FXMLLoader.load(getClass().getResource("Profile.fxml"));
Luncher.stage.setScene(new Scene(root));
} catch (IOException e) {
e.printStackTrace();
}
}
}
ProfileController.java
package loginApplication;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
public class ProfileController implements Initializable{
#FXML
private TextField name;
#FXML
private TextField email;
#FXML
private TextField gender;
#FXML
private TextField contact;
#FXML
private TextField age;
#FXML
private PasswordField password;
#Override
public void initialize(URL location, ResourceBundle resources) {
name.setText(Storage.getName());
age.setText(Storage.getAge());
gender.setText(Storage.getGender());
email.setText(Storage.getEmail());
contact.setText(Storage.getContact());
password.setText(Storage.getPassword());
//Open windows for sign up if nall else do this
if(Storage.getEmail() !=null)
{
//Disable everything
name.setDisable(true);
age.setDisable(true);
gender.setDisable(true);
email.setDisable(true);
contact.setDisable(true);
password.setDisable(true);
}
}
#FXML
private Button save;
#FXML
private Button edit;
#FXML
void editButton(ActionEvent event)
{
System.out.println("edit button");
//Active everything
name.setDisable(false);
age.setDisable(false);
gender.setDisable(false);
email.setDisable(false);
contact.setDisable(false);
password.setDisable(false);
}
#FXML
void saveButton(ActionEvent event) {
//Disable everything
name.setDisable(true);
age.setDisable(true);
gender.setDisable(true);
email.setDisable(true);
contact.setDisable(true);
password.setDisable(true);
removeLine();
addLine();
}
private void addLine() {
String line = name.getText() +"," +email.getText() +"," +password.getText() +"," +age.getText() +"," +gender.getText()+"," +contact.getText();
FileWriter file_writer;
try {
file_writer = new FileWriter("TextFiles/data.txt",true);
BufferedWriter buffered_Writer = new BufferedWriter(file_writer);
buffered_Writer.write(line);
buffered_Writer.flush();
buffered_Writer.close();
} catch (IOException e) {
System.out.println("Add line failed!!" +e);
}
}
private void removeLine() {
try
{
BufferedReader file = new BufferedReader(new FileReader("TextFiles/data.txt"));
String line;
String input = "";
while ((line = file.readLine()) != null)
{
//System.out.println(line);
if (line.contains(Storage.getEmail()))
{
line = "";
System.out.println("Line deleted.");
}
input += line + '\n';
}
FileOutputStream File = new FileOutputStream("TextFiles/data.txt");
File.write(input.getBytes());
file.close();
File.close();
}
catch (Exception e)
{
System.out.println("Problem reading file.");
}
}
}
Storage.java
package loginApplication;
public class Storage {
private static String Name;
private static String Age;
private static String Gender;
private static String Email;
private static String Contact;
private static String password;
// This is how u should do it but u can also make field public and use them directly
// for example -> 'Public static String Name' then use it as 'Storage.name'
public static String getName() {
return Name;
}
public static void setName(String name) {
Name = name;
}
public static String getAge() {
return Age;
}
public static void setAge(String age) {
Age = age;
}
public static String getGender() {
return Gender;
}
public static void setGender(String gender) {
Gender = gender;
}
public static String getEmail() {
return Email;
}
public static void setEmail(String email) {
Email = email;
}
public static String getContact() {
return Contact;
}
public static void setContact(String contact) {
Contact = contact;
}
public static String getPassword() {
return password;
}
public static void setPassword(String password) {
Storage.password = password;
}
}
Login.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onDragDetected="#loginButton" prefHeight="390.0" prefWidth="304.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="loginApplication.LoginController">
<children>
<TextField fx:id="email_textfield" layoutX="38.0" layoutY="83.0" prefHeight="34.0" prefWidth="229.0" promptText="Email">
<font>
<Font size="14.0" />
</font>
</TextField>
<PasswordField fx:id="password_textfield" layoutX="38.0" layoutY="152.0" prefHeight="34.0" prefWidth="229.0" promptText="Password" />
<Button layoutX="87.0" layoutY="222.0" mnemonicParsing="false" onAction="#loginButton" prefHeight="51.0" prefWidth="131.0" text="Login" textAlignment="CENTER" textFill="#328d38">
<font>
<Font name="Courier New Bold" size="22.0" />
</font>
</Button>
<Label fx:id="error_lab" layoutX="59.0" layoutY="284.0" prefHeight="29.0" prefWidth="229.0" textFill="#ee0c0c">
<font>
<Font size="18.0" />
</font>
</Label>
<Button layoutX="110.0" layoutY="284.0" mnemonicParsing="false" onAction="#signupButton" prefHeight="29.0" prefWidth="85.0" text="Sign up" textAlignment="CENTER" textFill="#3b21e4">
<font>
<Font name="Courier New Bold" size="15.0" />
</font>
</Button>
</children>
</AnchorPane>
Profile.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="420.0" prefWidth="560.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="loginApplication.ProfileController">
<children>
<Button fx:id="edit" layoutX="202.0" layoutY="363.0" mnemonicParsing="false" onAction="#editButton" prefHeight="26.0" prefWidth="111.0" text="Edit">
<font>
<Font size="14.0" />
</font>
</Button>
<TextField fx:id="name" layoutX="202.0" layoutY="28.0" prefHeight="25.0" prefWidth="329.0" promptText="Name">
<font>
<Font size="18.0" />
</font>
</TextField>
<TextField fx:id="email" layoutX="202.0" layoutY="242.0" prefHeight="25.0" prefWidth="329.0" promptText="Email">
<font>
<Font size="18.0" />
</font>
</TextField>
<TextField fx:id="gender" layoutX="202.0" layoutY="132.0" prefHeight="25.0" prefWidth="329.0" promptText="Gender">
<font>
<Font size="18.0" />
</font>
</TextField>
<TextField fx:id="contact" layoutX="202.0" layoutY="187.0" prefHeight="25.0" prefWidth="329.0" promptText="Contact">
<font>
<Font size="18.0" />
</font>
</TextField>
<TextField fx:id="age" layoutX="202.0" layoutY="81.0" prefHeight="25.0" prefWidth="329.0" promptText="Age">
<font>
<Font size="18.0" />
</font>
</TextField>
<Button fx:id="save" layoutX="420.0" layoutY="363.0" mnemonicParsing="false" onAction="#saveButton" prefHeight="26.0" prefWidth="111.0" text="Save">
<font>
<Font size="14.0" />
</font>
</Button>
<PasswordField fx:id="password" layoutX="202.0" layoutY="297.0" prefHeight="39.0" prefWidth="329.0" promptText="Password">
<font>
<Font size="18.0" />
</font>
</PasswordField>
<Label layoutX="35.0" layoutY="34.0" text="Name">
<font>
<Font name="Cambria Math" size="30.0" />
</font>
</Label>
<Label layoutX="35.0" layoutY="88.0" text="Age">
<font>
<Font name="Cambria Math" size="30.0" />
</font>
</Label>
<Label layoutX="35.0" layoutY="139.0" text="Gender">
<font>
<Font name="Cambria Math" size="30.0" />
</font>
</Label>
<Label layoutX="35.0" layoutY="194.0" text="Contact">
<font>
<Font name="Cambria Math" size="30.0" />
</font>
</Label>
<Label layoutX="35.0" layoutY="249.0" text="Email">
<font>
<Font name="Cambria Math" size="30.0" />
</font>
</Label>
<Label layoutX="35.0" layoutY="304.0" text="Password">
<font>
<Font name="Cambria Math" size="30.0" />
</font>
</Label>
</children>
</AnchorPane>
I hope this help if something wont work or u need to know something ask it :)
I suggest you use an SQLite database and Not textfile.
But using a Text file to make a small database it's a good practice.
To do this you need to create a .txt file that's your database
In a text file, you can store information many ways for example
Name, Email, Password, Age, Gender
Jack, jack#gmail.com, mypassword123, 18, male,
Adam, adam101#gmail.com, adampas1001, 21, female,
in this way you separating data with commas
Now you have to read each line 1 by 1
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
public class TextFileReader
{
// Location / count / List
private String text_File_Location; //location
private long count;
public TextFileReader(String url)
{
this.text_File_Location = url;
lineList = new ArrayList<String>();
countLines();
initFontCodeList();
}
//Counts number of lines mean number of profiles
private void countLines()
{
try {
count = Files.lines(Paths.get(text_File_Location)).count();
} catch (IOException e1) { System.err.println("TextFileReader : Count Failed" +e1); }
}
//init List
private void initFontCodeList() {
try
{
Path path = Paths.get(text_File_Location);
for (int i = 0; i < count; i++)
{
String line = Files.readAllLines(path).get(i);
//Acording to format Name, Email, Password, Age, Gender
String[] profile = line.split(",");
String name = profile[0];
String email = profile[1];
String Password = profile[2];
String age = profile[4];
String gender = profile[5];
}
}
catch (IOException e) {System.err.println("TextFileReader : ReadFile Failed");}
}
}
Now just use a couple of logic to check if an information entered on GUI is equal textfile information
Removing profile is just deleting that line
Modifying profile is just deleting that line and creating another line
This is all the basic how to start

JavaFX element is initialize with size 0

I have a problem when my FXML are initialized and theirs values are listen by listeners.
So my main window is a BorderPane
TOP = menu.fxml
CENTER = center1.fxml
BOTTOM = footer.fxml
When I click on one of buttons on center1Controller the CENTER fxml should changed to center2.fxml.
In center2.fxml I have a Pane that should be Anchor.anchorLeft=60 and anchorTop = anchorBottom
I was created an listener :
public void addTopOffsetListener() {
this.logonWindowPane.heightProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
double y = (newValue.doubleValue() - logonForm.getHeight()) / 2;
logonForm.setLayoutY(y);
}
});
}
But one my screen is reload the logonForm is in bad place. When I debug moment the initialization getHeight() returns 0.
It is placed in correct place after resizing window.
I was trying fixed size of this element on FXML and on CSS.
Actually I was find an workaround. When I initialize a screen2Controller a I have added this line
public void initialize(URL url, ResourceBundle rb) {
this.logonForm.resize(300, 400);
}
There is my Screen2 fxml :
<AnchorPane id="logonWindowPane" fx:id="logonWindowPane" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="genealogytree.application.fxmlcontrollers.LogonWindowController">
<stylesheets>
<URL value="#../styles/application_logon.css" />
</stylesheets>
<children>
<Pane id="logonForm" fx:id="logonForm" prefHeight="400" prefWidth="300" minWidth="300" minHeight="400" styleClass="projectPane" AnchorPane.rightAnchor="60.0" />
</children>
</AnchorPane>
And the FXML of element there I put in logonForm :
<Pane styleClass="logonFXForm" prefHeight="400" prefWidth="300" minWidth="300" minHeight="400" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="genealogytree.application.fxmlcontrollers.LogonFormController">
<stylesheets>
<URL value="#../styles/application_logon.css" />
</stylesheets>
<children>
<JFXPasswordField focusColor="#1f7f6a" layoutX="38.0" layoutY="133.0" maxWidth="224.0" minWidth="224.0" prefHeight="48.0" prefWidth="224.0" promptText="Password" unFocusColor="#253930">
<font>
<Font size="14.0" />
</font>
</JFXPasswordField>
<JFXTextField focusColor="#1f7f6a" layoutX="38.0" layoutY="54.0" maxWidth="224.0" minWidth="224.0" prefHeight="48.0" prefWidth="224.0" promptText="Login" unFocusColor="#253930">
<font>
<Font size="14.0" />
</font>
</JFXTextField>
<JFXButton buttonType="RAISED" graphicTextGap="8.0" layoutX="61.0" layoutY="224.0" prefHeight="48.0" prefWidth="178.0" ripplerFill="#32ae8f" styleClass="jfxButton" text="CONNECT" textAlignment="CENTER">
<font>
<Font name="System Bold" size="18.0" />
</font>
</JFXButton>
<Hyperlink layoutX="38.0" layoutY="305.0" prefHeight="25.0" prefWidth="250.0" text="Do not have an Account ? " />
<Hyperlink layoutX="38.0" layoutY="340.0" prefHeight="25.0" prefWidth="250.0" text="Forgotten Password ? " />
</children>
</Pane>
But there is another method to resolve my problem in FXML or CSS only ?

How to change screens in javafx on detecting radiobutton choice inside a buttonclick listener?

Elaborating my question further, I am developing a question bank in JavaFX. At the home screen, I wish to provide navigation based on radiobutton choice inside a button click.
e.g. If I select a radiobutton choice, and click on the button to proceed ahead, it should direct me to the FXML screen file I have created. To further explain what I am trying to stay, below is the GUI snapshot.
Question Bank GUI Link
I am pasting my code below :
Main HomeScreen FXML File :
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" prefHeight="548.0" prefWidth="721.0" styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="controller.HomefxmlController">
<children>
<GridPane alignment="CENTER" gridLinesVisible="false" layoutX="210.0" layoutY="149.0" prefHeight="171.0" prefWidth="373.0" visible="true">
<children>
<RadioButton fx:id="radioBlanks" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#onRadioBlankClick" text="Fill in the Blank" GridPane.columnIndex="0" GridPane.halignment="LEFT" GridPane.rowIndex="0" GridPane.valignment="CENTER" />
<RadioButton fx:id="radioMcq" mnemonicParsing="false" onAction="#onRadioMcqClick" text="MCQ" GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowIndex="0" />
<RadioButton fx:id="radioshortNote" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#onRadioSNclick" text="ShortNote" GridPane.columnIndex="0" GridPane.halignment="LEFT" GridPane.rowIndex="1" />
<RadioButton fx:id="radioLongAnswer" mnemonicParsing="false" onAction="#onRadioLNclick" text="LongAnswer" GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowIndex="1" />
<RadioButton fx:id="radioScenario" mnemonicParsing="false" onAction="#onRadioScenariocClick" text="Scenario" GridPane.columnIndex="0" GridPane.halignment="LEFT" GridPane.rowIndex="2" />
<RadioButton fx:id="radioTF" mnemonicParsing="false" onAction="#onRadioTFclick" text="True/False" GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowIndex="2" />
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
<Label alignment="CENTER" layoutX="234.0" layoutY="47.0" prefHeight="73.0" prefWidth="211.0" text="Question Bank" textAlignment="CENTER" underline="true" wrapText="false">
<font>
<Font name="Chiller" size="35.0" />
</font>
</Label>
<Button fx:id="btnProceed" layoutX="275.0" layoutY="378.0" mnemonicParsing="false" onAction="#onBtntProceed" prefHeight="48.0" prefWidth="129.0" text="Proceed" textFill="#252285">
<font>
<Font name="Linux Libertine G Regular" size="20.0" />
</font>
</Button>
</children>
<stylesheets>
<URL value="#homefxml.css" />
</stylesheets>
</AnchorPane>
FXML Controller File :
package controller;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.stage.Stage;
/**
* FXML Controller class
*
* #author Vishal
*/
public class HomefxmlController implements Initializable {
#FXML
private RadioButton radioBlanks;
#FXML
private RadioButton radioMcq;
#FXML
private RadioButton radioshortNote;
#FXML
private RadioButton radioLongAnswer;
#FXML
private RadioButton radioScenario;
#FXML
private RadioButton radioTF;
#FXML
private Button btnProceed;
ToggleGroup group;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
toggleGroupAssign();
}
public void toggleGroupAssign() {
group = new ToggleGroup();
radioBlanks.setToggleGroup(group);
radioMcq.setToggleGroup(group);
radioshortNote.setToggleGroup(group);
radioLongAnswer.setToggleGroup(group);
radioScenario.setToggleGroup(group);
radioTF.setToggleGroup(group);
}
#FXML
private void onBtntProceed(ActionEvent event) throws IOException {
// I am selecting just one checkbox at the moment for testing purpose..
if(radioTF.isSelected()){
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/tester.fxml"));
loader.load();
}
}
}
The PROBLEM is that NO ERROR appears at all. No compiletime error, no runtime, nothing ! It just doesn't work !
Kindly help me where exactly I am going wrong ?
loader.load() returns a Node, you don't assign
Take a look at this link
Loading new fxml in the same scene

Add elements to a Stage from a different controller

I have a MainInterface.fxml, with its own controller MainController in which a button opens a new Stage from NewCrawler.fxml with its associated controller AddCrawlerController.
It looks fine, but i need to add stuff into the MainInterface using the interface NewCrawler .
The goal is adding a new "itemCrawler" each time someone press the "Start Crawling" button in NewCrawler, like the one hardcoded in MainInterface. How Can I do that?
MainController.java
public class MainController {
#FXML private AnchorPane mainPane;
#FXML
public void addCrawlerInstance(String domain) { //TODO dynamically add itemCrawler (Like the one hardcoded in MainInterface
Button b = new Button(domain); //it is only a try to add elements from a different controller
mainPane.getChildren().add(b);
}
#FXML
private void createCrawler () throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("guifxml/NewCrawler.fxml"));
Scene scene = new Scene(root);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
}
AddCrawlerController.java
public class AddCrawlerController { //ADD Button from Main Interface
#FXML private Button abortButton;
#FXML private Button addCrawlerButton;
#FXML
private void abortCurrentWindow () {
Stage currentStage = (Stage) abortButton.getScene().getWindow();
currentStage.close();
}
#FXML
private void addNewCrawler () throws Exception { //TODO ref. Maincontroller.AddCrawlerInstance
FXMLLoader loader = new FXMLLoader(getClass().getResource("guifxml/MainInterface.fxml"));
Parent root = loader.load();
String d = "prova";
MainController controller = loader.getController();
controller.addCrawlerInstance("prova");
}
}
MainInterface.fxml
<VBox fx:id="mainApp" maxWidth="600.0" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wsa.gui.MainController">
<children>
<ButtonBar maxWidth="643.0" nodeOrientation="RIGHT_TO_LEFT" prefHeight="40.0" prefWidth="643.0">
<buttons>
<Button alignment="CENTER" mnemonicParsing="false" text="Set Path" />
<Button alignment="CENTER" mnemonicParsing="false" text="Delete" />
<Button alignment="CENTER" mnemonicParsing="false" text="Stop" />
<Button alignment="CENTER" mnemonicParsing="false" text="Start" />
<Button alignment="CENTER" mnemonicParsing="false" onMouseClicked="#createCrawler" text="Add" />
</buttons>
<VBox.margin>
<Insets />
</VBox.margin>
<padding>
<Insets right="5.0" />
</padding>
</ButtonBar>
<AnchorPane fx:id="mainPane" maxHeight="-1.0" maxWidth="-1.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
<children>
<Separator layoutY="2.0" prefHeight="3.0" prefWidth="645.0" />
<Pane fx:id="itemCrawler" prefHeight="52.0" prefWidth="645.0">
<children>
<Text layoutX="44.0" layoutY="34.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Domain">
<font>
<Font size="20.0" />
</font>
</Text>
<TextField editable="false" layoutX="124.0" layoutY="13.0" prefHeight="25.0" prefWidth="319.0" text="http://www.prova.org" />
<Button alignment="CENTER" layoutX="456.0" layoutY="13.0" mnemonicParsing="false" text="Add URI" />
<Button alignment="CENTER" layoutX="528.0" layoutY="13.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="60.0" text="Explore" />
<CheckBox layoutX="14.0" layoutY="18.0" mnemonicParsing="false" prefHeight="17.0" prefWidth="17.0" />
<Separator layoutY="51.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="3.0" prefWidth="645.0" />
</children>
</Pane>
</children>
</AnchorPane>
</children>
</VBox>
NewCrawler.fxml
<AnchorPane fx:controller="wsa.gui.AddCrawlerController" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextArea layoutX="119.0" layoutY="89.0" prefHeight="237.0" prefWidth="467.0" />
<Text layoutX="44.0" layoutY="52.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Domain" wrappingWidth="74.13671875">
<font>
<Font size="20.0" />
</font>
</Text>
<TextField layoutX="119.0" layoutY="32.0" prefHeight="25.0" prefWidth="467.0" />
<Text layoutX="44.0" layoutY="111.0" strokeType="OUTSIDE" strokeWidth="0.0" text="URI list" textAlignment="CENTER" wrappingWidth="74.13672208786011">
<font>
<Font size="20.0" />
</font>
</Text>
<Text layoutX="119.0" layoutY="85.0" strokeType="OUTSIDE" strokeWidth="0.0" text="one URI on each line " textAlignment="CENTER" wrappingWidth="467.00000166893005" />
<Button fx:id="addCrawlerButton" layoutX="260.0" layoutY="353.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="115.0" onMouseClicked="#addNewCrawler" text="Start Crawling" />
<Button fx:id="abortButton" layoutX="118.0" layoutY="353.0" mnemonicParsing="false" onMouseClicked="#abortCurrentWindow" prefHeight="25.0" prefWidth="115.0" text="Abort" />
</children>
</AnchorPane>
MainInterface
NewCrawler
What I understand is that you need a dynamic list of itemCrawlers.
Instead of hardcoding a newCrawler, you should use a ListView with a custom CellFactory that constructs custom ListCell to represent itemCrawler.
This tutorial tells you how to do that : http://docs.oracle.com/javafx/2/ui_controls/list-view.htm
I am not 100% sure about this, so correct me if I am wrong.
In the NewCrawler's controller you load the FXML in its constructor. Then you can instantiate the NewCrawler controller and work with it as with any other object inside your MainController.

Resources