有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Javafx类的java静态实例

我有一个包含main方法和start方法的主类。现在我还有很多其他的课程。例如,我有一个登录类、注册类等等。我有一个类,只处理当前登录用户的数据。需要从许多控制器访问该类。因为这个用户总是只有一个类的实例。我想知道的是什么是最好的方法,这样每个类都可以访问它并更新它

我目前正在应用的是在我的主类中创建logged user data type类的静态实例。然后访问它们

    public static loggedUserData user  = new loggedUserData();

然后从任何地方访问它:

    demo.user.set(...);

而类方法和字段是非静态的。我认为有更好的办法来解决这个问题


共 (1) 个答案

  1. # 1 楼答案

    您的user对象是构成MVC/MVP etc设计中模型一部分的应用程序数据:

    package application;
    
    import javafx.beans.property.ObjectProperty;
    import javafx.beans.property.SimpleObjectProperty;
    
    public class DataModel {
        private ObjectProperty<User> currentUser = new SimpleObjectProperty<>();
    
        public final ObjectProperty<User> currentUserProperty() {
            return this.currentUser;
        }
    
        public final User getCurrentUser() {
            return this.currentUserProperty().get();
        }
    
        public final void setCurrentUser(final User currentUser) {
            this.currentUserProperty().set(currentUser);
        }
    
    
    
        // other properties, etc...
    }
    

    在相对简单的应用程序中,我创建了一个引用模型实例的单例controller factory,并将其传递给任何可以接受它的控制器构造函数:

    package application;
    
    import java.lang.reflect.Constructor;
    
    import javafx.util.Callback;
    
    public enum ControllerFactory implements Callback<Class<?>, Object> {
    
        INSTANCE ;
    
        private final DataModel model = new DataModel();
    
        @Override
        public Object call(Class<?> type) {
            try {
                for (Constructor<?> constructor : type.getConstructors()) {
                    if (constructor.getParameterCount() == 1
                            && DataModel.class.isAssignableFrom(constructor.getParameterTypes()[0])) {
                        return constructor.newInstance(model);
                    }
                }
                return type.newInstance();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
    }
    

    (另一种选择,而不是在这里使用单例模式,就是使用一个接受DataModel的构造函数,并小心地始终传递对同一DataModel实例的引用。通常这样做是很自然的。)

    然后你可以有控制器,看起来像

    package application;
    
    import javafx.fxml.FXML;
    import javafx.scene.control.TextField;
    
    public class LoginController {
    
        private final DataModel model ;
    
        @FXML
        private TextField userNameTextField ;
    
        public LoginController(DataModel model) {
            this.model = model ;
        }
    
        @FXML
        private void login() {
            model.setCurrentUser(new User(userNameTextField.getText()));
        }
    
    }
    

    package application;
    
    import javafx.beans.binding.Bindings;
    import javafx.fxml.FXML;
    import javafx.scene.control.Label;
    
    public class SomeOtherController {
    
        private final DataModel model ;
    
        @FXML
        private Label userLabel ;
    
        public SomeOtherController(DataModel model) {
            this.model = model ;
        }
    
        public void initialize() {
    
            // Use EasyBind https://github.com/TomasMikula/EasyBind for
            // more robust binding to a "property of a property"
    
            userLabel.textProperty().bind(Bindings.select(model.currentUserProperty(), "userName"));
        }
    }
    

    如果使用以下习惯用法加载FXML文件,控制器将自动填充(共享)数据模型:

    package application;
    
    import java.io.IOException;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    
    public class Main extends Application {
        @Override
        public void start(Stage primaryStage) throws IOException {
            String resource = "Login.fxml" ;
            FXMLLoader loader = new FXMLLoader(getClass().getResource(resource));
            loader.setControllerFactory(ControllerFactory.INSTANCE);
            Parent root = loader.load();
            Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    对于更复杂的应用程序(或者简单地说,如果您喜欢基于约定的/自定的方法),考虑使用专用的JavaFX依赖注入框架,如Afterburner.fx