2016-09-25 77 views
0

我試圖製作兩個fxml文件。第一個是主要的fxml。第二個是TableView的fxml。我把它們放在一起。爲什麼我不能將項目添加到另一個FXML的表中?

這是主類:

package sceneBuilder; 

import java.io.IOException; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Scene; 
import javafx.scene.layout.BorderPane; 
import javafx.stage.Stage; 

public class Ana extends Application{ 

    private Stage window; 
    private BorderPane layout; 

    @Override 
    public void start(Stage args) throws Exception { 
     try{ 
      window = args; 
      showMainView(); 
      showMainItems(); 
     } 
     catch(Exception e){ 
      e.printStackTrace(); 
     } 
    } 


    private void showMainView() throws IOException { 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setLocation(Ana.class.getResource("interface.fxml")); 
     layout = loader.load(); 
     Scene scene = new Scene(layout); 
     window.setScene(scene); 
     window.show(); 

    } 

    private void showMainItems() throws IOException { 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setLocation(Ana.class.getResource("interface2.fxml")); 
     BorderPane layout2 = loader.load(); 
     layout.setCenter(layout2); 

    } 

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

這是主要的FXML的控制器(Controller.java):

package sceneBuilder; 

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.control.TextField; 
import javafx.scene.control.TreeItem; 
import javafx.scene.control.TreeView; 

public class Controller implements Initializable{ 

    //TreeView 
    @FXML 
    private TreeView<String> mainTree = new TreeView<>(); 

    //TextFields 
    @FXML 
    private TextField txtf1 = new TextField(); 
    @FXML 
    private TextField txtf2 = new TextField(); 
    @FXML 
    private TextField txtf3 = new TextField(); 

    @Override 
    public void initialize(URL location, ResourceBundle recources) { 
     TreeItem<String> root = new TreeItem<>("Tables"); 
     TreeItem<String> table1 = new TreeItem<>("Table-1"); 
     TreeItem<String> table2 = new TreeItem<>("Table-2"); 
     root.getChildren().add(table1); 
     root.getChildren().add(table2); 
     mainTree.setRoot(root); 
     mainTree.setShowRoot(false); 
    } 

    @FXML 
    void addClicked(ActionEvent event) throws Exception{ 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("interface2.fxml")); 
     Controller2 controller = loader.getController(); 
     controller.addData(txtf1.getText(), txtf2.getText(), txtf3.getText()); 
     } 

    @FXML 
    void deleteClicked(ActionEvent event){ 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("interface2.fxml")); 
     Controller2 controller = loader.getController(); 
     controller.addData(txtf1.getText(), txtf2.getText(), txtf3.getText()); 
     } 


} 

這是TableView中的控制器(Controller2.java):

package sceneBuilder; 

import java.net.URL; 
import java.util.ResourceBundle; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.fxml.FXML; 
import javafx.fxml.Initializable; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.PropertyValueFactory; 

public class Controller2 implements Initializable{ 

    //Table and columns 
    @FXML 
    private TableView<Product> table = new TableView<>(); 
    @FXML 
    private TableColumn<Product, String> nameColumn = new TableColumn<>(); 
    @FXML 
    private TableColumn<Product, String> priceColumn = new TableColumn<>(); 
    @FXML 
    private TableColumn<Product, String> quantityColumn = new TableColumn<>(); 


    //Items 
    ObservableList<Product> data = FXCollections.observableArrayList(
      new Product("Tablet", "20", "1200,00"), 
      new Product("Samsung Note 7", "50", "3450,00"), 
      new Product("Kitap", "1000", "50,00") 
    ); 

    //Column settings 
    @Override 
    public void initialize(URL location, ResourceBundle recources) { 
     nameColumn.setCellValueFactory(new PropertyValueFactory<Product, String>("ad")); 
     priceColumn.setCellValueFactory(new PropertyValueFactory<Product, String>("fiyat"));   
     quantityColumn.setCellValueFactory(new PropertyValueFactory<Product, String>("miktar")); 

     table.setItems(data); 
    } 

    public void addData(String t1, String t2, String t3){ 
     //Add data 
     Product satir = new Product(t1, t2, t3); 

     data.add(satir); 
    } 

    public void deleteData(){ 
     ObservableList<Product> productSelected, allProducts; 
     allProducts = table.getItems(); 
     productSelected = table.getSelectionModel().getSelectedItems(); 

     productSelected.forEach(allProducts::remove); 
    } 
} 

這就是問題所在:我想從TableView中添加或刪除項目。所以我創建了三個TextField和兩個按鈕。我爲按鈕設置了setOnAction方法。在Controller.java中,我獲取了我的TableView的FXML(interface2.fxml)文件。並嘗試啓動TableView的Controller(Controller2.java)中存在的addItem方法。但是,無論何時填充TextField並單擊添加或刪除按鈕,它都會給我java.lang.reflect.InvocationTargetExceptionjava.lang.NullPointerException。 我不知道爲什麼?請幫幫我。我不太瞭解英語,所以請不要寫下艱難的句子。 (除編程術語外)。

如果你需要,這些都是FXML文件: 主FXML:(interface.fxml)

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

<?import javafx.geometry.Insets?> 
<?import javafx.scene.control.Button?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.control.Menu?> 
<?import javafx.scene.control.MenuBar?> 
<?import javafx.scene.control.MenuItem?> 
<?import javafx.scene.control.TableColumn?> 
<?import javafx.scene.control.TableView?> 
<?import javafx.scene.control.TextField?> 
<?import javafx.scene.control.TreeView?> 
<?import javafx.scene.layout.BorderPane?> 
<?import javafx.scene.layout.HBox?> 
<?import javafx.scene.layout.Region?> 
<?import javafx.scene.layout.VBox?> 

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sceneBuilder.Controller"> 
    <top> 
     <VBox BorderPane.alignment="CENTER"> 
     <children> 
      <MenuBar> 
       <menus> 
       <Menu mnemonicParsing="false" text="Dosya"> 
        <items> 
        <MenuItem mnemonicParsing="false" text="Yeni" /> 
         <MenuItem mnemonicParsing="false" text="Kaydet" /> 
        </items> 
       </Menu> 
       <Menu mnemonicParsing="false" text="Yardım"> 
        <items> 
        <MenuItem mnemonicParsing="false" text="Hakkında" /> 
        </items> 
       </Menu> 
       </menus> 
      </MenuBar> 
      <HBox spacing="8.0"> 
       <children> 
        <TextField fx:id="txtf1" promptText="İsim" /> 
        <TextField fx:id="txtf2" layoutX="10.0" layoutY="10.0" promptText="Fiyat" /> 
        <TextField fx:id="txtf3" layoutX="175.0" layoutY="18.0" promptText="Miktar" /> 
        <Region HBox.hgrow="ALWAYS" /> 
        <Button maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#addClicked" text="Ekle" textAlignment="CENTER" textOverrun="CLIP"> 
        <padding> 
         <Insets bottom="4.0" left="10.0" right="10.0" top="4.0" /> 
        </padding></Button> 
        <Button layoutX="159.0" layoutY="10.0" mnemonicParsing="false" onAction="#deleteClicked" text="Sil"> 
        <padding> 
         <Insets bottom="4.0" left="15.0" right="15.0" top="4.0" /> 
        </padding></Button> 
       </children> 
       <padding> 
        <Insets bottom="8.0" left="8.0" right="8.0" top="8.0" /> 
       </padding> 
      </HBox> 
     </children> 
     </VBox> 
    </top> 
    <left> 
     <TreeView fx:id="mainTree" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" /> 
    </left> 
    <bottom> 
     <Label text="Sorunlar:" BorderPane.alignment="CENTER_LEFT"> 
     <padding> 
      <Insets bottom="8.0" left="8.0" right="8.0" top="8.0" /> 
     </padding></Label> 
    </bottom> 
    <center> 
     <TableView fx:id="table" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER"> 
     <columns> 
      <TableColumn fx:id="nameColumn" prefWidth="75.0" text="C1" /> 
      <TableColumn fx:id="priceColumn" prefWidth="75.0" text="C2" /> 
      <TableColumn fx:id="quantityColumn" prefWidth="75.0" text="Column X" /> 
     </columns> 
     </TableView> 
    </center> 
</BorderPane> 

而且TableView中的FXML(interface2.fxml):

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

<?import javafx.scene.control.TableColumn?> 
<?import javafx.scene.control.TableView?> 
<?import javafx.scene.layout.BorderPane?> 

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sceneBuilder.Controller2"> 
    <center> 
     <TableView fx:id="table" BorderPane.alignment="CENTER"> 
     <columns> 
      <TableColumn fx:id="nameColumn" maxWidth="200.0" minWidth="200.0" prefWidth="200.0" resizable="false" text="Ad" /> 
      <TableColumn fx:id="priceColumn" maxWidth="100.0" minWidth="100.0" prefWidth="100.0" text="Fiyat" /> 
      <TableColumn fx:id="quantityColumn" maxWidth="100.0" minWidth="100.0" prefWidth="100.0" text="Miktar" /> 
     </columns> 
     </TableView> 
    </center> 
</BorderPane> 
+0

loader.getController();你必須調用方法loader.load();這是擺脫NPE的第一個想法 – BadVegan

回答

2

你需要在兩個控制器之間共享數據。你可以這樣做的東西,如:

public class Controller2 implements Initializable { 

    // existing code... 

    public ObservableList<Product> getData() { 
     return data ; 
    } 
} 

然後給你的第一個控制器的數據的引用:

public class Controller implements Initializable { 

    private ObservableList<Product> data ; 

    public ObservableList<Product> getData() { 
     return data ; 
    } 

    public void setData(ObservableList<Product> data) { 
     this.data = data ; 
    } 

    // ... 

    @FXML 
    void addClicked(ActionEvent event) { 
     data.add(new Product(txtf1.getText(), txtf2.getText(), txtf3.getText()); 
    } 

    // etc ... 
} 

,然後你可以用

public class Ana extends Application{ 

    private Stage window; 
    private BorderPane layout; 

    @Override 
    public void start(Stage args) throws Exception { 
     try{ 
      window = args; 
      Controller mainController = showMainView(); 
      Controller2 controller = showMainItems(); 
      mainController.setData(controller.getData()); 
     } 
     catch(Exception e){ 
      e.printStackTrace(); 
     } 
    } 


    private Controller showMainView() throws IOException { 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setLocation(Ana.class.getResource("interface.fxml")); 
     layout = loader.load(); 
     Scene scene = new Scene(layout); 
     window.setScene(scene); 
     window.show(); 
     return loader.getController(); 
    } 

    private Controller2 showMainItems() throws IOException { 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setLocation(Ana.class.getResource("interface2.fxml")); 
     BorderPane layout2 = loader.load(); 
     layout.setCenter(layout2); 
     return loader.getController(); 
    } 

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

而且綁在一起了一切請參閱Applying MVC With JavaFx瞭解該想法的另一個版本。 (在回答這個問題時,數據會被移到自己的類中,這可能會更好。)

+0

是的,你說得對,這個代碼比NPE有更多的問題;) – BadVegan

+0

謝謝!!你幫了我很多。但我仍然不知道如何刪除數據。請給我一個簡短的回答:D –

+0

'data.remove(...)'將從表中刪除元素。 –

相關問題