简体   繁体   English

JavaFX使用fxml打开新窗口问题

[英]JavaFX open new window issue with fxml

I'm developing a password manager program. 我正在开发一个密码管理器程序。 When opening a new window in this program it throws an exception on the addEntry() mouse click event. 在此程序中打开新窗口时,它将在addEntry()鼠标单击事件上引发异常。 I have a Main class that opens the main window (with sample.fxml ) and a Controller class that manages to open the new window (with addNewEntryDialog.fxml ). 我有一个Main类,它打开主窗口(带有sample.fxml ),还有一个Controller类,它设法打开新窗口(带有addNewEntryDialog.fxml )。 Here's my code: 这是我的代码:

Main.java Main.java

package sample;

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

import java.io.IOException;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("/sample.fxml"));
        primaryStage.setTitle("Password Manager");
        primaryStage.setScene(new Scene(root, 800, 600));
        primaryStage.show();
    }

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

Controller.java Controller.java

package sample;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.ResourceBundle;

public class Controller implements Initializable {
    public ObservableList<Data> data;
    public TableView dbTable;
    public TableColumn siteColumn, usernameColumn, passwordColumn;

    public ToggleButton showPasswordToggle;


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        fillTable();
    }

    public void fillTable(){
        data = FXCollections.observableArrayList();
        String query = "SELECT * FROM accounts";

        try {
            Connection connection = connectToDatabase();
            ResultSet resultSet = connection.createStatement().executeQuery(query);

            while (resultSet.next()) {
                data.add(new Data(resultSet.getString(1), resultSet.getString(2), resultSet.getString(3)));
            }

            siteColumn.setCellValueFactory(new PropertyValueFactory("site"));
            usernameColumn.setCellValueFactory(new PropertyValueFactory("username"));
            passwordColumn.setCellValueFactory(new PropertyValueFactory("password"));

            dbTable.setItems(data);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @FXML
    public void addEntry() throws IOException {
        Stage stage = new Stage();
        Parent root = FXMLLoader.load(getClass().getResource("/addEntryDialog.fxml"));
        stage.setTitle("Add new entry");
        stage.setScene(new Scene(root, 800, 600));
        stage.show();
    }

addEntryDialog.fxml addEntryDialog.fxml

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

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <GridPane layoutX="28.0" layoutY="21.0" prefHeight="123.0" prefWidth="317.0">
         <columnConstraints>
            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
         </columnConstraints>
         <rowConstraints>
            <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
            <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
         </rowConstraints>
         <children>
            <Label layoutX="33.0" layoutY="26.0" text="Site:" />
            <Label layoutX="28.0" layoutY="78.0" text="Username:" GridPane.rowIndex="1" />
            <Label layoutX="44.0" layoutY="135.0" text="Password:" GridPane.rowIndex="2" />
            <TextField fx:id="siteField" layoutX="150.0" layoutY="21.0" GridPane.columnIndex="1" />
            <TextField fx:id="usernameField" layoutX="150.0" layoutY="73.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
            <PasswordField fx:id="passwordField" layoutX="150.0" layoutY="123.0" GridPane.columnIndex="1" GridPane.rowIndex="2" />
         </children>
      </GridPane>
      <Button layoutX="327.0" layoutY="163.0" mnemonicParsing="false" text="OK" />
      <Button layoutX="246.0" layoutY="163.0" mnemonicParsing="false" text="Cancel" />
   </children>
</Pane>

sample.fxml sample.fxml

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

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>

<Pane prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <TableView fx:id="dbTable" layoutX="4.0" layoutY="85.0" prefHeight="505.0" prefWidth="790.0">
        <columns>
          <TableColumn fx:id="siteColumn" prefWidth="263.0" text="Site" />
          <TableColumn fx:id="usernameColumn" prefWidth="263.0" text="Username" />
          <TableColumn fx:id="passwordColumn" prefWidth="263.0" text="Password" />
        </columns>
      </TableView>
      <GridPane layoutX="14.0" layoutY="27.0" prefHeight="25.0" prefWidth="263.0">
         <columnConstraints>
            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
         </columnConstraints>
         <rowConstraints>
            <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
         </rowConstraints>
         <children>
            <Button fx:id="addNewEntry" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onMouseClicked="#addEntry" text="Add.." GridPane.columnIndex="0" />
            <Button fx:id="removeEntry" layoutX="83.0" layoutY="14.0" mnemonicParsing="false" text="Remove.." GridPane.columnIndex="1" />
            <Button fx:id="editEntry" layoutX="178.0" layoutY="14.0" mnemonicParsing="false" text="Edit.." GridPane.columnIndex="2" />
         </children>
      </GridPane>
      <ToggleButton fx:id="showPasswordToggle" layoutX="671.0" layoutY="27.0" mnemonicParsing="false" text="Show Password" />
   </children>
</Pane>

STACK TRACE 堆栈跟踪

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
    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.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:352)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:388)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
    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.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
    ... 31 more
Caused by: javafx.fxml.LoadException: 
/home/umberto/passwordManager/out/production/passwordManager/addEntryDialog.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.loadImpl(FXMLLoader.java:3214)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
    at sample.Controller.addEntry(Controller.java:58)
    ... 41 more
Caused by: java.lang.NullPointerException
    at sample.Controller.loadTableData(Controller.java:45)
    at sample.Controller.initialize(Controller.java:30)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
    ... 49 more

Look at your addEntryDialog.fxml file. 查看您的addEntryDialog.fxml文件。 There is definition of this view's controller: 有此视图的控制器的定义:

<Pane ... fx:controller="sample.Controller>

JavaFX loads the view, looks for the controller and creates it. JavaFX加载视图,寻找控制器并创建它。 (At this moment another sample.Controller object is instantiated). (此时,另一个sample.Controller对象被实例化)。 After creating it sees that this controller implements Initializable interface, so it executes initialize method which in turn calls fillTable method and finally the statement siteColumn.setCellValueFactory(..) is reached. 创建后,它会看到该控制器实现了Initializable接口,因此它执行了initialize方法,该方法又调用fillTable方法,最后到达语句siteColumn.setCellValueFactory(..) The problem is that there's no siteColumn for addEntryDialog.fxml view - it has not been binded since there's no element on view with that id. 问题在于addEntryDialog.fxml视图没有siteColumn它没有被绑定,因为视图上没有具有该ID的元素。

Solution is to create proper controller for addEntryView.fxml and call it in xml fx:controller attribute. 解决方案是为addEntryView.fxml创建适当的控制器,并在xml fx:controller属性中调用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM