Переключение между пользовательскими моделями в приложении JavaFX - PullRequest
0 голосов
/ 18 сентября 2018

В моем текущем приложении JavaFX могут быть разные пользователи, которые имеют разные данные, относящиеся к ним.В разных частях приложения ярлыки, таблицы, графики и т. Д. Связаны с наблюдаемыми свойствами в пользовательском классе.

Проблема возникает при смене пользователей.Привязки все еще привязаны к предыдущему пользователю.Есть ли лучший способ обновить это, кроме повторного связывания всех частей пользовательского интерфейса при изменении пользователя?

Пользовательские данные хранятся в классе DataManager, который передается всем контроллерам, поэтому они имеют доступ кте же данные.

Пример DataManager:

public class DataManager {

    private ObservableList<User> userList = FXCollections.observableArrayList();
    private User currentUser;

   public void addUser(String name, int age, double height, double weight) {
        User newUser = new User(name, age, height, weight);
        try {
            DatabaseWriter.createDatabase();
            newUser.setId(UserDBOperations.insertNewUser(newUser));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        userList.add(newUser);
    }

    public void deleteUser(User user) {
        try {
            DatabaseWriter.createDatabase();
            UserDBOperations.deleteExistingUser(user.getId());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        userList.remove(user);
    }

    public updateCurrentUser();

    public changeUser();
}

Пример Класс пользователя:

public class User {

    private int id;
    private StringProperty name;
    private IntegerProperty age;
    private DoubleProperty height;
    private DoubleProperty weight;
    private DoubleProperty bmi;
    private DoubleProperty totalDistance;

    private ObservableList<Event> eventList = FXCollections.observableArrayList();

Существует ли лучший способ использования данных модели, который будет работать лучше в этой ситуации?Я могу предоставить больше кода / контекста приложения, если это поможет ответить.

Спасибо

РЕДАКТИРОВАТЬ 1:

public class ParentController {

    private DataManager dataManager = new DataManager();
    private ChildController childController1;
    private ChildController childController2;


    public void initializeChild() {
        childController1.setDataManager(dataManager);
        childController2.setDataManager(dataManager);
        // Controllers for different FXML Files
        //
    }
}

public class ChildController {

    /*  Child controller has elements which need data 
        from the DataManager
    */

    private DataManager dataManager;

    public void setDataManager(DataManager dataManager) {
        this.dataManager = dataManager;
    }
}

Основная проблема, которую я пытаюсь преодолеть,как сохранить базу данных, модель, хранящуюся в памяти, и все разные страницы в синхронизации с одной и той же моделью данных.Любые предложения или ресурсы, которые могли бы указать мне правильное направление, были бы хорошими.

РЕДАКТИРОВАТЬ 2: Добавил больше контекста о соединении с базой данных

1 Ответ

0 голосов
/ 18 сентября 2018

Проще говоря, вы должны привязать элементы управления, чтобы отобразить новые данные.

Когда вы связываете TextProperty с user.NameProperty, например, это связывание является специфическим для этого одного user объекта. Даже если вы смените пользователя, привязка по-прежнему будет указывать на первоначального пользователя.

Одним из возможных и простых решений является использование класса Singleton для хранения выбранного User. Это позволит выбранному пользователю быть видимым для всего вашего приложения:

User.java

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class User {

    private StringProperty username = new SimpleStringProperty();

    public User(String username) {
        this.username.set(username);
    }

    public String getUsername() {
        return username.get();
    }

    public StringProperty usernameProperty() {
        return username;
    }
}

GlobalData.java

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;

public class GlobalData {

    // Global property to hold the currently-selected user
    private ObjectProperty<User> selectedUser = new SimpleObjectProperty<>();

    private static GlobalData ourInstance = new GlobalData();

    public static GlobalData getInstance() {
        return ourInstance;
    }

    private GlobalData() {
    }

    public User getSelectedUser() {
        return selectedUser.get();
    }

    public ObjectProperty<User> selectedUserProperty() {
        return selectedUser;
    }

    public void setSelectedUser(User selectedUser) {
        this.selectedUser.set(selectedUser);
    }
}

Теперь, в ваших контроллерах пользовательского интерфейса, вам просто нужно создать слушателя для отслеживания изменений в selectedUser. Когда пользователь изменится, просто привяжите элементы пользовательского интерфейса в каждом контроллере.

Вот простой MCVE для демонстрации:

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.util.Random;

public class Main extends Application {

    // The Label which holds the username value
    private Label lblUsername = new Label();

    // Grab a reference to the GlobalData singleton
    private GlobalData globalData = GlobalData.getInstance();

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

    @Override
    public void start(Stage primaryStage) {

        // Create the initial sample User
        globalData.setSelectedUser(new User("User #1"));

        // Simple interface
        VBox root = new VBox(10);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // HBox to hold the username display
        HBox hBox = new HBox(5);
        hBox.setAlignment(Pos.CENTER);

        // Add the username labels to the HBox
        hBox.getChildren().addAll(
                new Label("Username:"),
                lblUsername
        );

        // Bind the Label to display the current selected user's username
        lblUsername.textProperty().bind(globalData.getSelectedUser().usernameProperty());

        // Here we use a listener on the the selectedUser property. When it changes, we
        // call the rebindUser() method to update the UI
        globalData.selectedUserProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue != null) {
                rebindUser(newValue);
            }
        });

        // Add a button that just changes the selectedUser
        Button button = new Button("Change User");

        // Set the action for the button to change users
        button.setOnAction(this::changeUser);

        // Add the HBox and button to the root layout
        root.getChildren().addAll(hBox, button);

        // Show the Stage
        primaryStage.setWidth(400);
        primaryStage.setHeight(200);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    private void changeUser(ActionEvent event) {

        // Create a new user with a random # at the end
        Random rnd = new Random();
        int num = rnd.nextInt(50 + 2);

        globalData.setSelectedUser(new User("User #" + num));
    }

    // This method accepts a new User object and updates all the displayed bindings
    private void rebindUser(User newUser) {
        lblUsername.textProperty().unbind();
        lblUsername.textProperty().bind(newUser.usernameProperty());
    }
}

Это дает следующий вывод:

Screenshot

Нажатие кнопки создаст случайного нового пользователя, обновит свойство selectedUser синглтона GlobalData, а Label будет обновлено с помощью метода rebindUser().

...