2016-02-26 102 views
0

我正在開發密碼管理器程序。在此程序中打開新窗口時,會在addEntry()鼠標單擊事件中引發異常。我有一個Main類打開主窗口(與sample.fxml)和Controller類,設法打開新窗口(與addNewEntryDialog.fxml)。這裏是我的代碼:JavaFX用fxml打開新窗口問題

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

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

<?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

<?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> 

堆棧跟蹤

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 
+1

那麼問題是什麼? –

+0

它調用addEntry()方法(鼠標點擊事件) –

+2

時會產生很多異常錯誤,因此請將堆棧跟蹤添加到您的問題中。 –

回答

0

看看你addEntryDialog.fxml文件。這個視圖的控制器的定義如下:

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

JavaFX加載視圖,查找控制器並創建它。 (此時另一個sample.Controller對象被實例化)。創建後看到該控制器實現了Initializable接口,因此它執行initialize方法,該方法又調用fillTable方法,最後到達語句siteColumn.setCellValueFactory(..)。問題是沒有siteColumn對於addEntryDialog.fxml視圖 - 它沒有綁定,因爲在該視圖上沒有該id。

解決方案是爲addEntryView.fxml創建適當的控制器,並在xml fx:controller屬性中調用它。

+0

我只需要addEntryView.fxml點擊「添加」按鈕添加一個新的表條目,siteColumn是表的一部分。所以我只需要從一個方法打開一個新窗口,我不關心表列。 –

+0

@UmbertoPalazzini沒錯,但是您已將'sample.Controller'定義爲'addEntryView'對話框的控制器。這就是爲什麼它會拋出空指針異常。創建新窗口涉及爲其創建控制器,控制器被創建並在初始化期間拋出NPE,因爲'addEntryView'上沒有列。 –