I have tried researching various pages regarding how to switch scenes or even stages with no luck to help my specific case. I am trying to create a program with a login form that manages a school library.
I have a login form that authenticates the user input with the method validateLogin(). If the login is successful (i.e. isLoginSuccess = true), I want my program to close primaryStage and open a new stage/window with the library management system.
Is it better to switch the scene on primaryStage or close primaryStage and open a new stage? How do you do that and should you do that from Main.java or is it fine to do it from LoginController.java? I'm having trouble switching scenes or even just creating a new stage from LoginController.java since primaryStage isn't recognized in that class.
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("login.fxml"));
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setScene(new Scene(root, 520, 400));
primaryStage.setResizable(false);
primaryStage.show();
}
//main() method is ignored in correctly deployed JavaFX application.
public static void main(String[] args)
{
launch(args);
}
}
LoginController.java
package sample;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.event.ActionEvent;
import javafx.stage.StageStyle;
import java.io.File;
import java.util.ResourceBundle;
//Can be removed, StackOverflow import
import java.io.BufferedReader;
import java.io.FileReader;
import java.net.URL;
public class LoginController implements Initializable
{
@FXML
private Button cancelButton;
@FXML
private Label loginMessageLabel;
@FXML
private ImageView brandingImageView;
@FXML
private ImageView lockImageView;
@FXML
private TextField usernameTextField;
@FXML
private PasswordField enterPasswordField;
@Override
public void initialize(URL url, ResourceBundle resourceBundle)
{
File brandingFile = new File("Images/LibManager.png");
Image brandingImage = new Image(brandingFile.toURI().toString());
brandingImageView.setImage(brandingImage);
File lockFile = new File("Images/LoginLock.png");
Image lockImage = new Image(lockFile.toURI().toString());
lockImageView.setImage(lockImage);
}
//Activates validateLogin() if there is input in text fields.
public void loginButtonOnAction(ActionEvent event)
{
if (usernameTextField.getText().isBlank() == false && enterPasswordField.getText().isBlank() == false)
{
validateLogin();
}
else
{
loginMessageLabel.setText("Please enter username and password");
}
}
//Closes login window.
public void cancelButtonOnAction(ActionEvent event)
{
Stage stage = (Stage) cancelButton.getScene().getWindow();
stage.close();
}
//Compares user input to txt file contents to authenticate.
public void validateLogin() {
{
try {
String location = "userdatabase.txt";
String username = usernameTextField.getText();
String password = enterPasswordField.getText();
FileReader fr = new FileReader(location);
BufferedReader br = new BufferedReader(fr);
String line, user, pass;
boolean isLoginSuccess = false;
while ((line = br.readLine()) != null) {
user = line.split(" ")[1].toLowerCase();
pass = line.split(" ")[2].toLowerCase();
if (user.equals(usernameTextField.getText()) && pass.equals(enterPasswordField.getText())) {
isLoginSuccess = true;
break;
}
}
if (!isLoginSuccess)
{
/*
public void startLibManager(Stage primaryStage) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("LibDatabase.fxml"));
Parent mainCallWindowFXML = loader.load();
secondaryStage.initStyle(StageStyle.UNDECORATED);
secondaryStage.setScene(new Scene(root, 520, 400));
secondaryStage.setResizable(false);
secondaryStage.show();
}
*/
/*
//use one of the components on your scene to get a reference to your scene object.
Stage stage = (Stage)tfCallerName.getScene.getWindow();//or use any other component in your controller
Scene mainCallWindow = new Scene (mainCallWindowFXML, 800, 600);
stage.setScene(newCallDetails);
stage.show(); //this line may be unnecessary since you are using the same stage.
*/
}
fr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
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.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="520.0" style="-fx-background-color: #FFFFFF;" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.LoginController">
<left>
<AnchorPane prefHeight="407.0" prefWidth="227.0" BorderPane.alignment="CENTER">
<children>
<ImageView fx:id="brandingImageView" fitHeight="400.0" fitWidth="226.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Images/LibManager.png" />
</image>
</ImageView>
</children></AnchorPane>
</left>
<right>
<AnchorPane prefHeight="400.0" prefWidth="332.0" style="-fx-background-color: FFFFFF;" BorderPane.alignment="CENTER">
<children>
<ImageView fx:id="lockImageView" fitHeight="32.0" fitWidth="46.0" layoutX="134.0" layoutY="65.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Images/LoginLock.png" />
</image>
</ImageView>
<Label layoutX="23.0" layoutY="157.0" prefHeight="17.0" prefWidth="60.0" text="Username" textFill="#01989e" />
<TextField fx:id="usernameTextField" layoutX="96.0" layoutY="152.0" prefWidth="173.0" promptText="Username" />
<Label layoutX="26.0" layoutY="205.0" text="Password" textFill="#01989e" />
<PasswordField fx:id="enterPasswordField" layoutX="96.0" layoutY="200.0" prefHeight="27.0" prefWidth="173.0" promptText="Password" />
<Button fx:id="loginButton" layoutX="22.0" layoutY="294.0" mnemonicParsing="false" onAction="#loginButtonOnAction" prefHeight="27.0" prefWidth="249.0" style="-fx-background-color: ff914d;" text="Login" textFill="WHITE" />
<Button fx:id="cancelButton" layoutX="22.0" layoutY="342.0" mnemonicParsing="false" onAction="#cancelButtonOnAction" prefHeight="27.0" prefWidth="249.0" style="-fx-background-color: ff914d;" text="Cancel" textFill="WHITE" />
<Label fx:id="loginMessageLabel" layoutX="26.0" layoutY="248.0" prefHeight="17.0" prefWidth="160.0" textFill="RED" />
</children></AnchorPane>
</right>
</BorderPane>