Initialize方法在Main类中的指定方法之前运行 [英] Initialize method runs before specified method in Main class

查看:329
本文介绍了Initialize方法在Main类中的指定方法之前运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将一个对象从一个控制器传递到另一个控制器。我传入BookViewController的rowData-object对初始化方法起作用至关重要,如果没有设置数据,那么NullPointerException确实会发生在我的情况下。

Im trying to pass an object from one controller to another. The rowData-object which I am passing into BookViewController is crucial for the initialize-method to work, if the data isn't set there's going to be a NullPointerException which indeed is happening in my case.

似乎initialize-method在setRowData-method之前运行。正如我所说,initialize-method依赖于setRowData-method已执行。

It seems that the initialize-method runs BEFORE the setRowData-method. And as I said, the initialize-method is dependent that the setRowData-method has executed.

我在这里错过了什么?

Main.java

Main.java

public class Main extends Application {

    private static Stage primaryStage;
    private static BorderPane mainLayout;

    @Override
    public void start(Stage primaryStage) throws Exception {
        Main.primaryStage = primaryStage;
        Main.primaryStage.setTitle("BookingApp");
        showMainView();
    }

    private void showMainView() throws IOException {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(Main.class.getResource("MainView.fxml"));
        mainLayout = loader.load();
        Scene scene = new Scene(mainLayout);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void showBookView(Trip rowData) throws IOException {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(Main.class.getResource("BookView.fxml"));
        BorderPane bookTrip = loader.load();

        BookViewController bvc = loader.getController();
        // The below method never runs.. why?
        bvc.setRowData(rowData);       

        Stage bookStage = new Stage();                
        bookStage.setTitle("BookingApp");
        bookStage.initModality(Modality.WINDOW_MODAL);
        bookStage.initOwner(primaryStage);
        Scene scene = new Scene(bookTrip);
        bookStage.setScene(scene);
        bookStage.showAndWait();
    }

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

BookViewController.java

BookViewController.java

public class BookViewController implements Initializable {

    private String dbUrl = "jdbc:postgresql://localhost:5432/BookingApp";

    private String dbUsername = "postgres";

    private String dbPassword = "secret";

    @FXML
    private TextField personnr;

    @FXML
    private TextField name;

    @FXML
    private TextField email;

    @FXML
    private TextField telnr;

    @FXML
    private Button addTraveler;

    @FXML
    private Button removeTraveler;

    @FXML
    private TableView<Traveler> travelers;

    @FXML
    private TableColumn<?, ?> personnrColumn;

    @FXML
    private TableColumn<?, ?> nameColumn;

    @FXML
    private TableColumn<?, ?> emailColumn;

    @FXML
    private TableColumn<?, ?> telnrColumn;

    @FXML
    private TableView<Trip> trips;

    @FXML
    private TableColumn<?, ?> originColumn;

    @FXML
    private TableColumn<?, ?> destinationColumn;

    @FXML
    private TableColumn<?, ?> departureColumn;

    @FXML
    private TableColumn<?, ?> arrivalColumn;

    @FXML
    private TableColumn<?, ?> driverColumn;

    @FXML
    private TableColumn<?, ?> priceAmountColumn;

    @FXML
    private TableColumn<?, ?> seatsColumn;

    @FXML
    private Button bookTrip;

    private Trip rowData;

    private ObservableList<Trip> tripData;

    public void setRowData(Trip rowData) {
        this.rowData = rowData;
        // The below println is never printed to the console..
        System.out.println("Test");
    }

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        addTraveler.setDisable(true);
        removeTraveler.setDisable(true);
        populateTravelPlan();
    }

    @FXML
    private void populateTravelPlan() {
        try {
            Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
            tripData = FXCollections.observableArrayList();
            ResultSet rs = null;
            System.out.println(rowData.getTrip1()); // Here it breaks
            System.out.println(rowData.getTrip2());
            System.out.println(rowData.getTrip3());
            if(rowData.getTrip1() != 0 && rowData.getTrip2() == 0 && rowData.getTrip3() == 0) {
                rs = conn.createStatement().executeQuery(
                        "select trip.tripid, connexion.origin, connexion.destination, trip.departure, trip.arrival, trip.driverpnr, trip.priceamount, trip.seats\r\n" + 
                        "from trip, connexion\r\n" + 
                        "where trip.tripid = " + rowData.getTrip1() + "\r\n" + 
                        "and trip.connexionid = connexion.connexionid\r\n" + 
                        "order by departure;");
            } else if(rowData.getTrip1() != 0 && rowData.getTrip2() != 0 && rowData.getTrip3() == 0) {
                rs = conn.createStatement().executeQuery(
                        "select trip.tripid, connexion.origin, connexion.destination, trip.departure, trip.arrival, trip.driverpnr, trip.priceamount, trip.seats\r\n" + 
                        "from trip, connexion\r\n" + 
                        "where trip.tripid = " + rowData.getTrip1() + "\r\n" + 
                        "and trip.connexionid = connexion.connexionid\r\n" + 
                        "union\r\n" + 
                        "select trip.tripid, connexion.origin, connexion.destination, trip.departure, trip.arrival, trip.driverpnr, trip.priceamount, trip.seats\r\n" + 
                        "from trip, connexion\r\n" + 
                        "where trip.tripid = " + rowData.getTrip2() + "\r\n" + 
                        "and trip.connexionid = connexion.connexionid\r\n" + 
                        "order by departure;");
            } else if(rowData.getTrip1() != 0 && rowData.getTrip2() != 0 && rowData.getTrip3() != 0) {
                rs = conn.createStatement().executeQuery(
                        "select trip.tripid, connexion.origin, connexion.destination, trip.departure, trip.arrival, trip.driverpnr, trip.priceamount, trip.seats\r\n" + 
                        "from trip, connexion\r\n" + 
                        "where trip.tripid = " + rowData.getTrip1() + "\r\n" + 
                        "and trip.connexionid = connexion.connexionid\r\n" + 
                        "union\r\n" + 
                        "select trip.tripid, connexion.origin, connexion.destination, trip.departure, trip.arrival, trip.driverpnr, trip.priceamount, trip.seats\r\n" + 
                        "from trip, connexion\r\n" + 
                        "where trip.tripid = " + rowData.getTrip2() + "\r\n" + 
                        "and trip.connexionid = connexion.connexionid\r\n" + 
                        "union\r\n" + 
                        "select trip.tripid, connexion.origin, connexion.destination, trip.departure, trip.arrival, trip.driverpnr, trip.priceamount, trip.seats\r\n" + 
                        "from trip, connexion\r\n" + 
                        "where trip.tripid = " + rowData.getTrip3() + "\r\n" + 
                        "and trip.connexionid = connexion.connexionid\r\n" + 
                        "order by departure;");
            }
            tripData.add(new Trip(rs.getInt(1), rs.getString(2), rs.getString(3), ""+rs.getTimestamp(4), ""+rs.getTimestamp(5), rs.getString(6), ""+rs.getInt(7), ""+rs.getInt(8)));
            while(rs.next()) {
                tripData.add(new Trip(rs.getInt(1), rs.getString(2), rs.getString(3), ""+rs.getTimestamp(4), ""+rs.getTimestamp(5), rs.getString(6), ""+rs.getInt(7), ""+rs.getInt(8)));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        trips.setItems(tripData);
    }
} 

例外

javafx.fxml.LoadException: 
/C:/Users/David/Desktop/eclipse/BookingApp1/bin/booking/BookView.fxml

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
    at booking.Main.showBookView(Main.java:35)
    at booking.MainViewController$1.handle(MainViewController.java:227)
    at booking.MainViewController$1.handle(MainViewController.java:1)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3470)
    at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3766)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:417)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
    at booking.BookViewController.populateTravelPlan(BookViewController.java:109)
    at booking.BookViewController.initialize(BookViewController.java:100)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
    ... 39 more 


推荐答案


似乎initialize方法在setRowData方法之前运行。

It seems that the initialize-method runs BEFORE the setRowData-method.

这是确实正确。作为执行 load的一部分, initialize()方法由 FXMLLoader 调用( ),必须在您有机会调用 setRowData(...)之前发生。

This is indeed correct. The initialize() method is called by the FXMLLoader as part of the execution of load(), which necessarily happens before you have a chance to call setRowData(...).


我在这里错过了什么?

What am I missing out on here?

没什么,真的。

有几种可能的修复方法。一个是简单地避免让 initialize()方法依赖于传递给 setRowData()的数据,并移动任何依赖于这些数据到后一种方法的代码。在这种情况下,这非常简单:

There are a couple of possible fixes. One is simply to avoid having the initialize() method depend on the data you pass to setRowData(), and move any code that does depend on those data to the latter method. This is pretty trivial in this case:

public void setRowData(Trip rowData) {
    this.rowData = rowData;
    populateTravelPlan();
}

@Override
public void initialize(URL arg0, ResourceBundle arg1) {
    addTraveler.setDisable(true);
    removeTraveler.setDisable(true);
    // don't do this here:
    // populateTravelPlan();
}

如果您不喜欢该解决方案,另一个选择是设置代码中的控制器而不是FXML中的控制器。简而言之,您将从FXML文件中删除 fx:controller 属性,然后在加载FXML时,创建一个控制器实例,调用 setRowData( )(或以其他方式初始化行数据,例如通过构造函数),并在 FXMLLoader <上调用 setController() / code>。 传递参数JavaFX FXML 中详细介绍了此解决方案。

If you don't like that solution, one other option is to set the controller in code instead of in the FXML. Briefly, you would remove the fx:controller attribute from the FXML file, and then when you load the FXML, create a controller instance, call setRowData() (or otherwise initialize the row data, e.g. via a constructor), and call setController() on the FXMLLoader. This solution is described in detail in Passing Parameters JavaFX FXML.

一个该解决方案的缺点是,如果将Scene Builder用于FXML设计,Scene Builder将失去一些功能(因为它不再知道用于创建控制器的类)。如果你想保留这个功能,可以使用控制器工厂。

One disadvantage of that solution is that if you use Scene Builder for the FXML design, Scene Builder will lose some functionality (as it's no longer aware of the class used to create the controller). If you want to keep that functionality, you can use a controller factory.

对于那个解决方案,我会修改控制器,以便将行数据传递给构造函数:

For that solution, I would modify the controller so that the row data were passed to a constructor:

public class BookViewController implements Initializable {

    // @FXML-annotated fields omitted...

    private final Trip rowData;

    public BookViewController(Trip rowData) {
        this.rowData = rowData ;
    }

    // remove this, it is now initialized in the constructor
    // public void setRowData(Trip rowData) {
    //     this.rowData = rowData;
    //     // The below println is never printed to the console..
    //     System.out.println("Test");
    // }

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        addTraveler.setDisable(true);
        removeTraveler.setDisable(true);
        populateTravelPlan();
    }

    // etc...
}

此构造函数将阻止 FXMLLoader 使用其默认方法创建控制器实例,因此将控制器工厂提供给加载程序以覆盖控制器的创建方式:

This constructor will prevent the FXMLLoader from creating a controller instance using its default method, so supply a controller factory to the loader to override how the controller is created:

public static void showBookView(Trip rowData) throws IOException {
    FXMLLoader loader = new FXMLLoader();
    loader.setLocation(Main.class.getResource("BookView.fxml"));
    loader.setControllerFactory(type -> {
        if (type == BookViewController.class) {
            return new BookViewController(rowData);
        }
        // default behavior: need this in case there are <fx:include> in the FXML
        try {
            return type.getConstructor().newInstance();
        } catch (Exception exc) {
            // fatal...
            throw new RuntimeException(exc);
        }
    });
    BorderPane bookTrip = loader.load();

    Stage bookStage = new Stage();                
    bookStage.setTitle("BookingApp");
    bookStage.initModality(Modality.WINDOW_MODAL);
    bookStage.initOwner(primaryStage);
    Scene scene = new Scene(bookTrip);
    bookStage.setScene(scene);
    bookStage.showAndWait();
}

这篇关于Initialize方法在Main类中的指定方法之前运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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