2016-02-26 3 views
0

Je développe un programme de gestion de mot de passe. Lors de l'ouverture d'une nouvelle fenêtre dans ce programme, il déclenche une exception sur l'événement de clic de souris addEntry(). J'ai une classe Main qui ouvre la fenêtre principale (avec sample.fxml) et une classe Controller qui parvient à ouvrir la nouvelle fenêtre (avec addNewEntryDialog.fxml). Voici mon code:JavaFX ouvre une nouvelle fenêtre avec 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> 

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

Alors, quel est le problème? –

+0

il donne beaucoup d'erreurs d'exception lors de l'appel de la méthode addEntry() (événement cliqué de la souris) –

+2

alors ajoutez la trace de la pile à votre question. –

Répondre

0

Regardez votre fichier addEntryDialog.fxml. Il y a une définition du contrôleur de cette vue:

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

JavaFX charge la vue, recherche le contrôleur et le crée. (À ce moment, un autre objet sample.Controller est instancié). Après la création, il voit que ce contrôleur implémente l'interface Initializable, donc il exécute la méthode initialize qui à son tour appelle la méthode fillTable et enfin l'instruction siteColumn.setCellValueFactory(..) est atteinte. Le problème est qu'il n'y a pas siteColumn pour addEntryDialog.fxml vue - il n'a pas été lié car il n'y a aucun élément sur la vue avec cet ID.

La solution consiste à créer un contrôleur approprié pour addEntryView.fxml et à l'appeler dans l'attribut xml fx:controller.

+0

J'ai seulement besoin de addEntryView.fxml lorsque vous cliquez sur un bouton "Ajouter" pour ajouter une nouvelle entrée de table, siteColumn fait partie de la table. J'ai donc seulement besoin d'ouvrir une nouvelle fenêtre à partir d'une méthode, je ne me soucie pas des colonnes de la table. –

+0

@UmbertoPalazzini C'est vrai, mais vous avez défini 'sample.Controller' comme le contrôleur du dialogue' addEntryView'. C'est pourquoi il déclenche une exception de pointeur nul. La création d'une nouvelle fenêtre implique la création d'un contrôleur pour elle, le contrôleur est créé et lève NPE pendant l'initialisation car il n'y a pas de colonnes sur 'addEntryView'. –