使用 Scenebuilder for JAVAFx 的登录应用程序的 MVC 架构 [英] MVC architecture for a login appplication using Scenebuilder for JAVAFx

查看:79
本文介绍了使用 Scenebuilder for JAVAFx 的登录应用程序的 MVC 架构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试开发一个登录应用程序,它从用户那里获取用户名和密码并检查数据库,如果它是真的,那么它会更改为另一个视图.如果不是,它会显示警报.我尝试做一个基本版本,其中密码存储在文本文件中,它只检查控制器类.但是我想实现MVC架构.我无法为此完成模型类和控制器类.我该怎么做?

I am trying to develop a login application which takes the username and password from the user and check with the database and if it's true then it changes to another view .if not it displays the alert. I tried doing a basic version where the password is stored in the text file and it checks in the controller class only. But I want to implement MVC architecture. I am unable to complete the model class and controller class for this. How can I do this?

查看类:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.effect.DropShadow?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>

<AnchorPane nodeOrientation="LEFT_TO_RIGHT" prefHeight="720.0" prefWidth="1280.0" style="-fx-background-color: #ffffff;" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gload.views.main.LoginScreenctrl">
    <VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="720.0" prefWidth="1280.0" style="-fx-background-color: #F3F3F3;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <AnchorPane minHeight="118.0" minWidth="0.0" prefHeight="150.0" prefWidth="1280.0">
            <HBox alignment="TOP_CENTER" layoutX="177.0" layoutY="30.0" prefHeight="90.0" prefWidth="860.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="177.0" AnchorPane.rightAnchor="243.0" AnchorPane.topAnchor="30.0">
                <Text fx:id="gloadtext" fill="#00bbde" fontSmoothingType="LCD" stroke="WHITE" strokeType="OUTSIDE" styleClass="centered" text="GLOAD for" textAlignment="CENTER" wrappingWidth="401.13671875" HBox.hgrow="NEVER">
                    <font>
                        <Font name="Times New Roman Bold" size="68.0" />
                    </font>
                </Text>

                <ImageView fitHeight="75.0" fitWidth="417.0" pickOnBounds="true" preserveRatio="true">
                    <image>
                        <Image url="@../../../main/resources/Images/1200px-Logo.svg.png" />
                    </image>
                </ImageView>
            </HBox>
        </AnchorPane>

        <Separator nodeOrientation="LEFT_TO_RIGHT" prefHeight="23.0" prefWidth="1263.0" />

        <AnchorPane maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="528.0" prefWidth="1280.0" stylesheets="@../../../main/resources/style.css" VBox.vgrow="ALWAYS">
            <VBox alignment="TOP_CENTER" layoutX="275.0" layoutY="21.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="504.0" prefWidth="640.0" style="-fx-background-color: #ffffff;" stylesheets="@../../../main/resources/style.css" AnchorPane.leftAnchor="275.0" AnchorPane.topAnchor="21.0">
                <ImageView fitHeight="60.0" fitWidth="330.0" pickOnBounds="true" preserveRatio="true">
                    <image>
                        <Image url="@../../../main/resources/Images/1200px-Logo.svg.png" />
                    </image>

                    <VBox.margin>
                        <Insets top="10.0" />
                    </VBox.margin>
                </ImageView>

                <Text fill="#22286f" fontSmoothingType="LCD" strokeType="OUTSIDE" strokeWidth="0.0" text="Welcome to ****" textAlignment="CENTER">
                    <font>
                        <Font name="Impact" size="30.0" />
                    </font>
                </Text>

                <Text fontSmoothingType="LCD" strokeType="OUTSIDE" strokeWidth="0.0" text="Sign In to Continue" textAlignment="CENTER">
                    <font>
                        <Font name="Impact" size="22.0" />
                    </font>
                </Text>

                <AnchorPane prefHeight="344.0" prefWidth="640.0" style="-fx-background-color: #ffffff;">
                    <TextField fx:id="user" layoutX="199.0" layoutY="71.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="28.0" prefWidth="263.0" promptText="Username" AnchorPane.bottomAnchor="240.0" AnchorPane.leftAnchor="199.0" AnchorPane.rightAnchor="178.0" AnchorPane.topAnchor="71.0" />*

                    <PasswordField fx:id="password" layoutX="201.0" layoutY="145.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onKeyPressed="#enter" prefHeight="28.0" prefWidth="263.0" promptText="Password" AnchorPane.bottomAnchor="166.0" AnchorPane.leftAnchor="201.0" AnchorPane.rightAnchor="176.0" AnchorPane.topAnchor="145.0" />

                    <Text layoutX="199.0" layoutY="56.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Username:" wrappingWidth="152.291015625" AnchorPane.bottomAnchor="282.1064453125" AnchorPane.leftAnchor="199.0" AnchorPane.rightAnchor="288.708984375" AnchorPane.topAnchor="39.9599609375">
                        <font>
                            <Font name="Times New Roman Bold" size="18.0" />
                        </font>
                    </Text>

                    <Text layoutX="198.0" layoutY="132.0" strokeType="OUTSIDE" strokeWidth="0.0" text="eDir password:" AnchorPane.bottomAnchor="206.1064453125" AnchorPane.leftAnchor="198.0" AnchorPane.rightAnchor="324.5078125" AnchorPane.topAnchor="115.9599609375">
                        <font>
                            <Font name="Times New Roman Bold" size="18.0" />
                        </font>
                    </Text>

                    <ButtonBar layoutX="209.0" layoutY="241.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="37.0" prefWidth="213.0" AnchorPane.bottomAnchor="64.0" AnchorPane.leftAnchor="209.0" AnchorPane.rightAnchor="218.0" AnchorPane.topAnchor="241.0">
                        <padding>
                            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
                        </padding>

                        <opaqueInsets>
                            <Insets />
                        </opaqueInsets>

                        <buttons>
                            <Button fx:id="login" lineSpacing="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#makeLogin" prefHeight="35.0" prefWidth="197.0" text="Log In">
                                <padding>
                                    <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
                                </padding>
                            </Button>
                        </buttons>
                    </ButtonBar>
                </AnchorPane>

                <padding>
                    <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
                </padding>

                <effect>
                    <DropShadow blurType="GAUSSIAN" />
                </effect>
            </VBox>

            <VBox.margin>
                <Insets />
            </VBox.margin>
        </AnchorPane>
    </VBox>
</AnchorPane>

控制器类:

package gload.views.main;

import gload.model.Login;
import gload.utils.SceneLoader;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.Scanner;

public class LoginScreenctrl implements Initializable {
    private Login model;

    public LoginScreenctrl(Login model) {
        this.model = model;
    }

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    @FXML
    public TextField user;

    @FXML
    private PasswordField password;

    @FXML
    private Button login;

    public TextField getUser() {
        return model.getUser();
    }

    public void setUser(TextField user) {
        model.setUser(user);
    }

    @FXML
    public PasswordField getPassword() {
        return model.getPassword();
    }

    public void setPassword(PasswordField password) {
        model.setPassword(password);
    }

    public boolean grantAccess;

    public void setGrantAccess(boolean grantAccess) {
        this.grantAccess = grantAccess;
    }

    public void enter(KeyEvent keyEvent) {                                                  
        // to login with enter button on password field
        if (keyEvent.getCode() == KeyCode.ENTER)
            login.fire();
    }

    @FXML
    public void makeLogin(ActionEvent  event) throws IOException {
        // This method gets triggered and check the value with the database to grant
        String username = user.getText();
        String pass = password.getText();
        File userdata = new File("users.txt"); // When Clicked on Login
        System.out.println("File Opened");
        try {
            Scanner read = new Scanner(userdata);
            int i = 0; // count lines in the file
            while (read.hasNextLine()) {
                i++;
                // loop through every line in the file and check against the user name & password (Saved in Pairs of lines)
                if(read.nextLine().equals(username)) { // if the same user name
                    System.out.println("Read " + i + " Line");
                    i++;
                    if(read.nextLine().equals(pass)) { // check password
                        setGrantAccess(true); // if also same, change boolean to true
                        System.out.println("Read " + i + " Line");
                        i++;
                        break; // and break the for-loop
                    }
                }
            }

            if (grantAccess) {
                // let the user continue
                // and do other stuff, for example: move to next window
                SceneLoader.loadscene("/gload/views/main/welcome.fxml",
                        (Stage)((Node) event.getSource()).getScene().getWindow());
                setUser(user);
                //new WelcomeCtrl().logas.setText("User logged in as "+ user);
                //new WelcomeCtrl().displayLogAs();
            } else {
                // return Alert message to notify the deny
                // display error
                Alert dialog = new Alert(Alert.AlertType.ERROR);
                dialog.setTitle("Not able to Login");
                dialog.setHeaderText("Incorrect Username or Password");
                dialog.setContentText("You have entered incorrect username or Password.\nPlease try Again");
                dialog.showAndWait();
            }

            read.close();
            System.out.println("File Closed");
        } catch (FileNotFoundException e) {
            System.out.println("Error : DATABASE ACCESS ERROR!");
            e.printStackTrace();
        }
    }

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        // Nothing
    }
}

模型类:

package gload.model;

import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;

public class Login {
    private TextField user;
    private PasswordField password;

    public TextField getUser() {
        return user;
    }

    public void setUser(TextField user) {
        this.user = user;
    }

    public PasswordField getPassword() {
        return password;
    }

    public void setPassword(PasswordField password) {
        this.password = password;
    }

    public Login() {
        String username = user.getText();
        String pass = password.getText();
    }
}

主类:

package gload;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.util.Objects;

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getResource("views/main/loginscreen.fxml")));
        primaryStage.setTitle("GLOAD");
        primaryStage.setScene(new Scene(root, 1280, 720));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

推荐答案

MVC 更容易理解,没有 FXML 的东西,它有一个令人困惑的控制器"属于自己的类.

MVC is easier to understand without the FXML stuff, which has a confusing "Controller" class of its own.

登录模型:

public class LoginModel {

    private StringProperty user = new SimpleStringProperty("");
    private StringProperty password = new SimpleStringProperty("");

    public String getUser() {
        return user.get();
    }

    public StringProperty userProperty() {
        return user;
    }

    public void setUser(String user) {
        this.user.set(user);
    }

    public String getPassword() {
        return password.get();
    }

    public StringProperty passwordProperty() {
        return password;
    }

    public void setPassword(String password) {
        this.password.set(password);
    }
}

登录控制器:

public class LoginController {

    private LoginViewBuilder viewBuilder;
    private LoginModel model = new LoginModel();
    private Stage stage;

    public LoginController(Stage stage) {
        this.stage = stage;
        viewBuilder = new LoginViewBuilder(model, () -> checkAccess());
    }

    public Region getView() {
        return viewBuilder.getView();
    }

    private void checkAccess() {
        if (model.getUser().equals("fred") && model.getPassword().equals("password")) {
            loadMainApplication();
        } else {
            displayErrorMessage();
        }
    }

    private void displayErrorMessage() {
        Alert dialog = new Alert(Alert.AlertType.ERROR);
        dialog.setTitle("Not able to Login");
        dialog.setHeaderText("Incorrect Username or Password");
        dialog.setContentText("You have entered incorrect username or Password.\nPlease try Again");
        dialog.showAndWait();
    }

    private void loadMainApplication() {
        VBox vBox = new VBox(new ImageView(new Image("/images/win.png")));
        stage.setScene(new Scene(vBox));
    }

}

接下来,登录 ViewBuilder.

Next, a Login ViewBuilder.

就我个人而言,我认为 FXML 是一种可怕的时间浪费,但是如果您坚持使用它,那么对 FMXL 加载器的调用和 FXML 控制器的实例化将进入 getView()代码>方法在这里.当然,您需要找到一种方法将模型的引用传递给 FXML 控制器,以便将模型属性绑定到 TextField/PasswordField 控件.

Personally, I think that FXML is a horrible waste of time, but if you insist on using it, then the call to the FMXL loader and the instantiation of the FXML Controller would go in the getView() method here. Of course, you'll need to find a way to pass a reference to the Model to the FXML Controller in order to bind the Model properties to the TextField/PasswordField controls.

如果你这样做,那么你会看到 FXML 控制器实际上只是 MVC 的视图部分 - 而不是控制器:

If you do that, then you'll see that the FXML Controller is really just the View part of MVC - not the Controller:

public class LoginViewBuilder {

    private final LoginModel model;
    private Runnable actionRunnable;

    public LoginViewBuilder(LoginModel model, Runnable actionRunnable) {
        this.model = model;
        this.actionRunnable = actionRunnable;
    }

    public Region getView() {
        HBox userHBox = new HBox(10, new Text("User ID: "), createBoundTextField(model.userProperty()));
        HBox passwordHBox = new HBox(10, new Text("Password: "), createBoundPasswordField(model.passwordProperty()));
        Button loginButton = new Button("Login");
        loginButton.setOnAction(evt -> actionRunnable.run());
        VBox results = new VBox(10, userHBox, passwordHBox, loginButton);
        results.setAlignment(Pos.CENTER);
        return results;
    }

    private Node createBoundPasswordField(StringProperty boundProperty) {
        PasswordField results = new PasswordField();
        results.textProperty().bindBidirectional(boundProperty);
        return results;
    }

    private Node createBoundTextField(StringProperty boundProperty) {
        TextField results = new TextField("");
        results.textProperty().bindBidirectional(boundProperty);
        return results;
    }
}

还有一个主要:

public class LoginMain extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setScene(new Scene(new LoginController(primaryStage).getView()));
        primaryStage.setTitle("GLOAD");
        primaryStage.show();
    }
}

这篇关于使用 Scenebuilder for JAVAFx 的登录应用程序的 MVC 架构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆