当前位置: 首页 > 知识库问答 >
问题:

JavaFx控制器初始化顺序-多次调用数据库

梁丘赞
2023-03-14

我有一个标准的JavaFX应用程序,可以扩展应用程序。我展示的第一个页面是一个仪表板,上面有打开其他应用程序的按钮。这很好,第一个应用程序是一个名为AdminController的管理页面,允许用户对模型对象(用户、联系人、产品)进行CRUD操作。每个实体都是管理视图上的一个选项卡。因此,在我的主管理FXML(使用SceneBuilder)中,我使用fx包括其他FXML页面:包括用户选项卡、联系人选项卡和产品选项卡。同样,这些都包括在一个管理。fxml有自己的控制器。

<Tab fx:id="contactsTab" onSelectionChanged="#goToContacts" text="Contact">
   <content>
     <fx:include source="/fxml/manager_contacts_tab.fxml" fx:id="contact" />
   </content
<Tab/>

我的想法是在AdminController中加载每个页面所需的资源、用户/联系人/产品,这样我使用的每个fx:include都可以使用相同的对象。因为有些标签页需要所有这些资源,比如用户来管理关联,而其他标签页(比如product)只需要一个产品列表。我的主控制器看起来像这样

public class AdminController {
  @FXML
  UserController userController;
  @FXML
  ProductController productController;
  @FXML
  ContactController contactController;

@FXML
public void initialize
    // at this point userController already ran, and called DB so it calls it again here
    if (users == null) {
        this.users = FXCollections.observableArrayList(userDao.getAllWithProductsAndContacts());
    }
    if (products == null) {
        this.products = FXCollections.observableArrayList(productDao.getAll());
    }
    if (contacts == null) {
        this.contacts = FXCollections.observableArrayList(contactDao.getAll());
    }
    contactController.setContacts(contact);
    // set other resources, like products
}

逻辑上讲,我认为AdminController的初始化方法将首先运行,这将允许我在子控制器中设置我需要的任何对象,因为我可以访问它们,但现在发生的是子控制器首先运行,例如使用ContactController

public class ContactController {
    @FXML
    public void initialize() {
        if (contacts == null) {
            this.contacts = FXCollections.observableArrayList(contactDao.getAll());
        }
    }

所以我的应用程序初始化方法运行的顺序,他们被包括在admin.fxmluserController,联系Controller,最后productController

我想我的问题可以归结为如何在子控制器之间共享对象,这样当单击一个新选项卡时,如果该选项卡的资源列表与前一个选项卡相同,则不会启动新的数据库调用——在我的示例中,当我加载用户页面时,它需要联系人列表和产品列表,但ContactController除外

共有1个答案

锺离飞尘
2023-03-14

在你的情况下,如果你一次加载“所有”联系人,我可能会在你初始化一个控制器之前调用数据库。

package main;

import javafx.application.Application;
import javafx.stage.Stage;

public class Main extends Application {

    public void start(Stage window) throws Exception {
        // Database call goes here!
        DatabaseManager.initialize();


        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        // Whatever window initialization stuff you need to do
        window.show();
    }

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

}

现在是DatabaseManager课程

package sample;

public class DatabaseManager {

    public static void initialize() {
        // Query the database for your information.
        // Little pseudo code here
        Data.setUsers(Database.userQuery);
        Data.setContacts(Database.contactQuery);
        Data.setProducts(Database.productQuery);
    }

}

现在是数据类

package sample;

public class Data {

    public static ArrayList<User> getUsers() {
        return users;
    }

    public static void setUsers(ArrayList<User> users) {
        this.users = users;
    }

    public static ArrayList<Contact> getContacts() {
        return contacts;
    }

    public static void setContacts(ArrayList<Contact> contacts) {
        this.contacts = contacts;
    }

    public static ArrayList<Product> getProducts() {
        return products;
    }

    public static void setProducts(ArrayList<Product> products) {
        this.products = products;
    }

    private static ArrayList<User> users = new ArrayList<User>();
    private static ArrayList<Contact> contacts = new ArrayList<Contact>();
    private static ArrayList<Product> products = new ArrayList<Product>();

}

现在你的控制器只需要呼叫

this.contacts = FXCollections.observableArrayList(Data.getContacts());

这将使您的联系人阵列列表准备就绪。

还要注意,这就是所谓的“将其加载到内存中”。换句话说,你将所有信息存储在计算机内存中,并从那里访问它。对于一个庞大的数据库来说,这是行不通的,因为你的计算机没有足够的大脑空间。不管怎样,希望这有帮助。

 类似资料:
  • 我正在构建一个Javafx gui应用程序,我正面临这个问题。我的程序有多个场景,所以我有不同的FXML文件和控制器类。问题是,在第一个“主菜单”(这是我的应用程序中弹出的第一个)场景中,在控制器的构造函数中,我调用了一些从数据库加载数据的重型方法等等。所以会发生什么。在接下来的场景中我确实有“主菜单按钮”,即切换到主菜单场景!所以每次我回到“主菜单”场景时,构造函数都会调用大量加载数据的方法。但

  • 问题内容: 我的课看起来像这样: 在FXMLLoader创建相应的控制器(在所给出的实例经由文件通过调用第一默认构造,然后)方法: 输出为: 那么,为什么存在这种方法呢?使用构造函数或方法初始化控制器所需的东西有什么区别? 问题答案: 简而言之:首先调用构造函数,然后@FXML填充所有带注释的字段,然后再调用。因此,构造函数无权访问引用文件中定义的组件的字段,而有权访问它们。 引用FXML简介:

  • 我的类如下所示: 通过首先调用默认构造函数,然后调用方法,创建相应控制器的实例(在文件中通过给出): 输出为: 那么,为什么方法会存在呢?使用构造函数或方法初始化控制器所需的东西有什么区别? 谢谢你的建议!

  • 问题内容: 我有一个AngularJs应用程序,我想在其中一开始就加载消息和应用程序版本,并将它们保存在本地存储中,然后再在控制器中使用它们。我现在所拥有的是每个控制器中的服务调用(目前为三个): 我只想获取一次应用程序版本并将其存储在此处。我不必每次都检查版本,对(如果新版本中添加了新消息)? 我发现使用$routeProvider的建议,但我的应用程序不是SPA。所以我需要其他想法/建议。对你

  • 我有一个Java Spring Boot应用程序,在我的Maven pom.xml中将Flyway配置为依赖项(我有一个父pom和一个项目pom...Flyway是在我的项目pom中定义的)。 application.properties中只有几个条目: 我可以运行一个maven任务来让Flyway运行来创建/更新我的数据库,然后针对该数据库运行我的应用程序,但是我很难通过运行我的应用程序(这在p

  • 问题内容: 我想延迟控制器的初始化,直到从服务器收到必要的数据为止。 我找到了针对Angular1.0.1的解决方案:延迟AngularJS路由更改,直到加载模型以防止闪烁,但无法使其与Angular1.1.0一起使用 模板 ​ JavaScript http://jsfiddle.net/dTJ9N/1/ 问题答案: 由于$ http返回了promise,因此创建自己的deferred仅在htt