【问题标题】:JavaFX Adding Rows to TableView on Different PageJavaFX在不同页面上向TableView添加行
【发布时间】:2017-02-22 00:22:25
【问题描述】:

好的,我一直在解决这个程序的一些问题,我想我终于明白了哪里出了问题。我正在尝试稍微遵循本教程:http://docs.oracle.com/javafx/2/fxml_get_started/fxml_tutorial_intermediate.htm 但我的程序在与表视图不同的 FXML 页面上添加了一行。我认为该程序无法将两者连接起来。我已经研究过试图找到让他们互相交谈的方法(把所有东西都放在一个控制器中但它不喜欢它,尝试通过类传递控制器但没有用{可能做错了尽管})。我的程序中还有整数和双精度数,这在该教程中没有涉及,所以我尝试自己解决这些问题(可能比我做的更好)。

但现在我只专注于弄清楚它为什么一直在思考

data = partTable.getItems();

为空(AddPartController 中的第 77 行)。任何帮助或其他 FXML/JavaFX 教程将不胜感激(尽管我已经看过很多)。

FXMLDocument.fxml(主页)

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

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.cell.*?> 
<?import javafx.collections.*?>
<?import fxmltableview.*?>
<?import ims.Part?> 
<?import ims.Inhouse?> 
<?import ims.Outsourced?> 

<BorderPane id="main" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ims.FXMLDocumentController" >
    <top>
        <Label fx:id="mainTitle" text="Inventory Management System" /> 
    </top>
    <center>
        <HBox fx:id="holding">
            <children>
                <VBox styleClass="contentBox">
                    <children>
                        <HBox styleClass="topBox">
                            <HBox styleClass="subHeading">
                                <Label text="Parts" />
                            </HBox>
                            <HBox styleClass="searchBox">
                                <Button text="Search" />
                                <TextField />
                            </HBox>
                        </HBox>
                        <TableView fx:id="partTable" styleClass="dataTable">
                            <columns>
                                <TableColumn text="Part ID">
                                    <cellValueFactory>
                                        <PropertyValueFactory property="id" />
                                    </cellValueFactory>
                                </TableColumn>
                                <TableColumn fx:id="nameColumn" text="Part Name">
                                    <cellValueFactory>
                                        <PropertyValueFactory property="name" />
                                    </cellValueFactory>
                                </TableColumn>
                                <TableColumn text="Inventory Level">
                                    <cellValueFactory>
                                        <PropertyValueFactory property="instock" />
                                    </cellValueFactory>
                                </TableColumn>
                                <TableColumn text="Price/Cost per Unit">
                                    <cellValueFactory>
                                        <PropertyValueFactory property="price" />
                                    </cellValueFactory>
                                </TableColumn>
                            </columns>
                            <items>
                                <FXCollections fx:factory="observableArrayList">
                                    <Inhouse name="Part 1" price="5.00" instock="5" max="10" min="1" />
                                    <Inhouse name="Part 2" price="7.00" instock="2" max="11" min="2" />
                                </FXCollections>
                            </items>
                            <sortOrder>
                                <fx:reference source="nameColumn" />
                            </sortOrder>
                        </TableView>
                        <HBox styleClass="modificationButtons">
                            <children>
                                <Button onAction="#addPart" text="Add" /> 
                                <Button onAction="#modifyPart" text="Modify" /> 
                                <Button text="Delete" /> 
                            </children>
                        </HBox>
                    </children>
                </VBox>
                <VBox styleClass="contentBox">
                    <children>
                        <HBox styleClass="topBox">
                            <HBox styleClass="subHeading">
                                <Label text="Products" />
                            </HBox>
                            <HBox styleClass="searchBox">
                                <Button text="Search" />
                                <TextField />
                            </HBox>
                        </HBox>
                        <TableView fx:id="productTable" styleClass="dataTable">
                            <columns>
                                <TableColumn text="Part ID" />
                                <TableColumn text="Part Name" />
                                <TableColumn text="Inventory Level" />
                                <TableColumn text="Price/Cost per Unit" />
                            </columns>
                        </TableView>
                        <HBox styleClass="modificationButtons">
                            <children>
                                <Button onAction="#addProduct" text="Add" /> 
                                <Button onAction="#modifyProduct" text="Modify" /> 
                                <Button text="Delete" /> 
                            </children>
                        </HBox>
                    </children>
                </VBox>
            </children>
        </HBox>
    </center>
    <bottom>
        <HBox fx:id="exitButton">
            <children>
                <Button onAction="#closeProgram" text="Exit" />
            </children>
        </HBox>
    </bottom>
</BorderPane>

FXMLDocumentController

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ims;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;

/**
 *
 * @author chelseacamper
 */
public class FXMLDocumentController implements Initializable {

    @FXML
    private Label label;


    @FXML
    private void addPart(ActionEvent event) throws IOException {
        Parent add_part_parent = FXMLLoader.load(getClass().getResource("addPart.fxml"));
        Scene add_part_scene = new Scene(add_part_parent);
        add_part_scene.getStylesheets().add("style.css");
        Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        app_stage.setScene(add_part_scene);
        app_stage.show();
    }

    @FXML
    private void modifyPart(ActionEvent event) throws IOException {
        Parent modify_part_parent = FXMLLoader.load(getClass().getResource("modifyPart.fxml"));
        Scene modify_part_scene = new Scene(modify_part_parent);
        modify_part_scene.getStylesheets().add("style.css");
        Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        app_stage.setScene(modify_part_scene);
        app_stage.show();
    }

    @FXML
    private void addProduct(ActionEvent event) throws IOException {
        Parent add_product_parent = FXMLLoader.load(getClass().getResource("addProduct.fxml"));
        Scene add_product_scene = new Scene(add_product_parent);
        add_product_scene.getStylesheets().add("style.css");
        Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        app_stage.setScene(add_product_scene);
        app_stage.show();
    }

    @FXML
    private void modifyProduct(ActionEvent event) throws IOException {
        Parent modify_product_parent = FXMLLoader.load(getClass().getResource("modifyProduct.fxml"));
        Scene modify_product_scene = new Scene(modify_product_parent);
        modify_product_scene.getStylesheets().add("style.css");
        Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        app_stage.setScene(modify_product_scene);
        app_stage.show();
    }    

    @FXML
    private void closeProgram(ActionEvent event) throws IOException {
        Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        app_stage.close();
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    

}

addPart.fxml

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

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

<BorderPane id="addPage" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ims.AddPartController">
    <fx:define>
        <ToggleGroup fx:id="inOutGroup" />
    </fx:define>
    <center>
        <VBox fx:id="verticalHolding">
            <children>
                <HBox fx:id="topRow">
                    <Label text="Add Part"/>
                    <RadioButton fx:id="inhouse" toggleGroup="$inOutGroup" text="In-House"/>
                    <RadioButton fx:id="outsourced" toggleGroup="$inOutGroup" selected="true" text="Outsourced"/>
                </HBox>
                <HBox styleClass="fullWidth">
                    <HBox styleClass="halfWidthLeft">
                        <Label text="ID" />
                    </HBox>
                    <HBox styleClass="halfWidthRight">
                        <TextField promptText="Auto Gen - Disabled" />
                    </HBox>
                </HBox>
                <HBox styleClass="fullWidth">
                    <HBox styleClass="halfWidthLeft">
                        <Label text="Name" />
                    </HBox>
                    <HBox styleClass="halfWidthRight">
                        <TextField fx:id="partNameField" promptText="Part Name" />
                    </HBox>
                </HBox>
                <HBox styleClass="fullWidth">
                    <HBox styleClass="halfWidthLeft">
                        <Label text="Inv" />
                    </HBox>
                    <HBox styleClass="halfWidthRight">
                        <TextField fx:id="partInstockField" promptText="Inv" />
                    </HBox>
                </HBox>
                <HBox styleClass="fullWidth">
                    <HBox styleClass="halfWidthLeft">
                        <Label text="Price/Cost" />
                    </HBox>
                    <HBox styleClass="halfWidthRight">
                        <TextField fx:id="partPriceField" promptText="Price/Cost" />
                    </HBox>
                </HBox>
                <HBox styleClass="fullWidth">
                    <HBox styleClass="halfWidthLeft">
                        <Label text="Max" />
                    </HBox>
                    <HBox styleClass="halfWidthRight">
                        <TextField styleClass="smallTextField" fx:id="partMaxField" promptText="Max" />
                        <Label text="Min" />
                        <TextField styleClass="smallTextField" fx:id="partMinField" promptText="Min" />
                    </HBox>
                </HBox>
                <HBox styleClass="fullWidth">
                    <HBox styleClass="halfWidthLeft">
                        <Label fx:id="inhouseLabel" text="Machine ID" />
                        <Label fx:id="outsourcedLabel" text="Company Name" />
                    </HBox>
                    <HBox styleClass="halfWidthRight">
                        <TextField fx:id="inhouseTextField" promptText="Mach ID" />
                        <TextField fx:id="outsourcedTextField" promptText="Comp Nm" />
                    </HBox>
                </HBox>
                <HBox styleClass="fullWidth">
                    <HBox styleClass="halfWidthLeft">
                    </HBox>
                    <HBox styleClass="halfWidthRight">
                        <Button onAction="#addInhouse" text="Save" />
                        <Button onAction="#backToMain" text="Cancel" />
                    </HBox>
                </HBox>
            </children>
        </VBox>
    </center>
</BorderPane>

添加部件控制器

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ims;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.stage.Stage;

/**
 * FXML Controller class
 *
 * @author chelseacamper
 */
public class AddPartController implements Initializable {
    @FXML
    ToggleButton inhouse;
    @FXML
    ToggleButton outsourced;
    @FXML
    Label inhouseLabel;
    @FXML
    Label outsourcedLabel;
    @FXML
    TextField inhouseTextField;
    @FXML
    TextField outsourcedTextField;
    @FXML
    private TableView<Inhouse> partTable;
    @FXML
    private TextField partNameField;
    @FXML
    private TextField partInstockField;
    @FXML
    private TextField partPriceField;
    @FXML
    private TextField partMaxField;
    @FXML
    private TextField partMinField;

    /**
     * Initializes the controller class.
     * @param url
     * @param rb
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        inhouseLabel.visibleProperty().bind( inhouse.selectedProperty() );
        outsourcedLabel.visibleProperty().bind( outsourced.selectedProperty() );
        inhouseTextField.visibleProperty().bind( inhouse.selectedProperty() );
        outsourcedTextField.visibleProperty().bind( outsourced.selectedProperty() );
        inhouseLabel.managedProperty().bind( inhouse.selectedProperty() );
        outsourcedLabel.managedProperty().bind( outsourced.selectedProperty() );
        inhouseTextField.managedProperty().bind( inhouse.selectedProperty() );
        outsourcedTextField.managedProperty().bind( outsourced.selectedProperty() );

    }

    @FXML
    public void addInhouse(ActionEvent event){
        ObservableList<Inhouse> data;
        data = partTable.getItems();
        data.add(new Inhouse(partNameField.getText(),
                Integer.parseInt(partInstockField.getText()),
                Double.parseDouble(partPriceField.getText()),
                Integer.parseInt(partMaxField.getText()),
                Integer.parseInt(partMinField.getText()),
                Integer.parseInt(inhouseTextField.getText())
//                Integer.parseInt(outsourcedTextField.getText())
                ));
        partNameField.setText("");
        partInstockField.setText(String.valueOf(partInstockField));
        partPriceField.setText(String.valueOf(partPriceField));
        partMaxField.setText(String.valueOf(partMaxField));
        partMinField.setText(String.valueOf(partMinField));
        inhouseTextField.setText(String.valueOf(inhouseTextField));
//        outsourcedTextField.setText(String.valueOf(outsourcedTextField));
    }

    @FXML
    private void backToMain(ActionEvent event) throws IOException {
        Parent add_main_parent = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        Scene add_main_scene = new Scene(add_main_parent);
        add_main_scene.getStylesheets().add("style.css");
        Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        app_stage.setScene(add_main_scene);
        app_stage.show();
    }

}

单击添加然后保存时出现的错误(甚至不必输入内容)

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1770)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1653)
    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:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8390)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    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$MouseHandler.process(Scene.java:3758)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3486)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2495)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:350)
    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$350(GlassViewEventHandler.java:385)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$294/109927940.get(Unknown Source)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:404)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:384)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:927)
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:497)
    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:497)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1765)
    ... 46 more
Caused by: java.lang.NullPointerException
    at ims.AddPartController.addInhouse(AddPartController.java:77)
    ... 56 more

【问题讨论】:

    标签: javafx javafx-2 javafx-8 fxml


    【解决方案1】:

    addPart.fxmlfx:id="partTable" 中没有元素。因此partTable 为空,并且

    partTable.getItems();
    

    抛出空指针异常。

    您需要将partTable 注入到定义它的 FXML 的控制器中:

    public class FXMLDocumentController implements Initializable {
    
        @FXML
        private Label label;
    
        @FXML
        private TableView<Inhouse> partTable ;
    
        // ...
    }
    

    AddPartController 只需要访问与表关联的项目列表,因此您可以为它定义一个字段,以及一个初始化它的方法:

    public class AddPartController implements Initializable {
    
        // ...
    
        private ObservableList<Inhouse> tableItems ;
    
        public void setTableItems(ObservableList<Inhouse> tableItems) {
            this.tableItems = tableItems ;
        }
    
        // ...
    }
    

    然后在加载时设置项目addPart.fxml

    @FXML
    private void addPart(ActionEvent event) throws IOException {
    
        FXMLLoader loader = new FXMLLoader(getClass().getResource("addPart.fxml"));
        Parent add_part_parent = loader.load();
    
        AddPartController addPartController = loader.getController();
        addPartController.setTableItems(partTable.getItems());
    
        Scene add_part_scene = new Scene(add_part_parent);
        add_part_scene.getStylesheets().add("style.css");
        Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        app_stage.setScene(add_part_scene);
        app_stage.show();
    }
    

    当然你只需要

    @FXML
    public void addInhouse(ActionEvent event){
    
        tableItems.add(new Inhouse(partNameField.getText(),
                Integer.parseInt(partInstockField.getText()),
                Double.parseDouble(partPriceField.getText()),
                Integer.parseInt(partMaxField.getText()),
                Integer.parseInt(partMinField.getText()),
                Integer.parseInt(inhouseTextField.getText())
                //  Integer.parseInt(outsourcedTextField.getText())
                ));
    }
    

    (FWIW我不知道是什么

    partInstockField.setText(String.valueOf(partInstockField));
    

    etc etc 应该做的。)

    【讨论】:

    • 感谢您的快速回复和解释!我很感激。对于这两行,我得到“找不到符号变量加载器”:Parent add_part_parent = loader.load(); AddPartController addPartController = loader.getController(); Netbeans 建议我创建了一个名为“loader”的字段,我认为这不正确,但如果我这样做,它会返回另一个错误“找不到符号方法 load()”。有什么想法吗?
    • @Chelsea 如果你仔细看我写的代码,你会发现在Parent add_part_parent = loader.load();之前的那一行,我定义了一个名为loader的变量。
    • 你说得对,这 100% 是我的错。非常感谢!我现在正试图弄清楚如何在向表格添加内容时更新表格,但至少它不再给我那个错误了。 (:
    • @Chelsea 好吧,从技术上讲,表格正在更新,但是由于您替换了显示它的场景,您实际上不太可能看到更新...
    • 所以不是完全替换屏幕,有没有办法导航到它不会被替换的地方?
    猜你喜欢
    • 2021-12-04
    • 2017-01-14
    • 1970-01-01
    • 2015-11-02
    • 2013-06-13
    • 2020-02-07
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    相关资源
    最近更新 更多