JavaFX用fxml打开新窗口问题

时间:2016-02-26 19:01:39

标签: java javafx

我正在开发一个密码管理器程序。在此程序中打开一个新窗口时,它会在$(this)鼠标单击事件上引发异常。我有一个addEntry()类打开主窗口(带有Main)和一个sample.fxml类,它设法打开新窗口(带Controller)。这是我的代码:

Main.java

addNewEntryDialog.fxml

Controller.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);
    }
}

addEntryDialog.fxml

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();
    }

sample.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>

STACK TRACE

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

1 个答案:

答案 0 :(得分:1)

查看您的addEntryDialog.fxml文件。这个视图的控制器有定义:

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

JavaFX加载视图,查找控制器并创建它。 (此时实例化另一个sample.Controller对象)。创建后,看到此控制器实现了Initializable接口,因此它执行initialize方法,后者又调用fillTable方法,最后到达语句siteColumn.setCellValueFactory(..)。问题是siteColumn视图没有addEntryDialog.fxml - 它没有被绑定,因为在该视图中没有带有该ID的元素。

解决方案是为addEntryView.fxml创建适当的控制器,并在xml fx:controller属性中调用它。