2017-09-25 3 views
0

Comment puis-je faire une action de bouton pour l'édition TableView. Je dois mettre du texte de TextArea à la table quand je touche le bouton. Et si mis System.out.println dans inputToTable() c'est un travail.Actions JavaFx entre les contrôleurs

public class InputController { 

    public TextArea inputArea; 
    public Button inputButton; 
    private TableController tableController; 

    public void initialize() { 
     tableControllerInit(); 
    } 

    public void inputToTable() { 
     if(inputArea.getText() != "") { 
      tableController.tableInfo.setItems(FXCollections.observableArrayList(new InputObject(inputArea.getText()))); 
     } 
    } 

    private void tableControllerInit() { 
     try { 
      FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("table.fxml")); 
      fxmlLoader.load(); 
      tableController = fxmlLoader.getController(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

public class TableController { 

    @FXML TableView<InputObject> tableInfo; 
    @FXML TableColumn<InputObject, String> col1; 

    public void initialize() { 
     col1.setCellValueFactory(new PropertyValueFactory<>("text")); 
    } 
} 

public class Controller implements Initializable { 

    @Override 
    public void initialize(URL location, ResourceBundle resources) { 

    } 
} 

public class InputObject { 
    String text; 

    public InputObject(String text) { 
     this.text = text; 
    } 

    public String getText() { 
     return text; 
    } 

    public void setText(String text) { 
     this.text = text; 
    } 
} 



<BorderPane fx:controller="sample.Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1"> 
    <left> 
     <fx:include source="table.fxml"/> 
    </left> 
    <center> 
     <fx:include source="input.fxml"/> 
    </center> 
</BorderPane> 

<TableView fx:controller="sample.TableController" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:id="tableInfo" prefHeight="400.0" prefWidth="330.0"> 
    <columns> 
     <TableColumn fx:id="col1" prefWidth="75.0" text="Output" /> 
    </columns> 
    <columnResizePolicy> 
     <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> 
    </columnResizePolicy> 
</TableView> 

<VBox fx:controller="sample.InputController" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" alignment="TOP_CENTER" prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER"> 
    <children> 
     <TextArea fx:id="inputArea" prefHeight="188.0" prefWidth="270.0" /> 
     <Button fx:id="inputButton" onAction="#inputToTable" mnemonicParsing="false" text="Input"> 
      <VBox.margin> 
       <Insets bottom="30.0" left="30.0" right="30.0" top="30.0" /> 
      </VBox.margin> 
     </Button> 
    </children> 
</VBox> 

Répondre

1

Vous chargez table.fxml deux fois: une fois par l'fx:include dans le fichier principal FXML, et une fois dans InputController, via le FXMLLoader vous créez dans la méthode tableControllerInit(). Par conséquent, deux instances de TableController sont créées, l'une associée à la première interface utilisateur que vous chargez à partir de table.fxml, et l'autre associée à la deuxième interface utilisateur que vous chargez à partir de table.fxml.

L'interface utilisateur que vous chargez via fx:include est affichée dans le fichier VBox défini dans le fichier FXML principal. L'interface utilisateur que vous chargez avec le FXMLLoader n'est jamais affichée (en fait, vous ne gardez jamais de référence, vous appelez simplement loader.load() et ignorez le résultat). Lorsque vous essayez de mettre à jour les éléments de la table (avez-vous vraiment l'intention de remplacer tous les éléments existants, au fait?), Vous faites référence à la seconde instance de contrôleur, associée à l'interface utilisateur qui n'est jamais affichée. Par conséquent, vous mettez à jour une table qui n'est pas affichée et vous ne voyez aucun résultat.

Ce que vous devez vraiment faire est de partager les mêmes données entre les deux contrôleurs associés aux deux fx:include s. Vous pouvez le faire simplement en injectant ces deux contrôleurs dans le contrôleur principal, comme décrit dans la section "Nested Controllers" de la documentation.

D'abord, donner les éléments fx:includefx:id attributs:

<BorderPane fx:controller="sample.Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1"> 
    <left> 
     <fx:include fx:id="table" source="table.fxml"/> 
    </left> 
    <center> 
     <fx:include fx:id="input" source="input.fxml"/> 
    </center> 
</BorderPane> 

Ensuite, vous pouvez injecter les contrôleurs dans le contrôleur principal en créant des champs avec le mot "Controller" annexé au fx:id. Créer une seule liste observable, qui représentera la liste des éléments affichés dans la table, et le transmettre à chaque contrôleur:

public class Controller implements Initializable { 

    @FXML 
    private TableController tableController ; 

    @FXML 
    private InputController inputController ; 

    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
     ObservableList<InputObject> items = FXCollections.observableArrayList(); 
     tableController.setTableItems(items); 
     inputController.setTableItems(items); 
    } 
} 

Enfin, il suffit de définir les méthodes évidentes dans chacune des deux autres contrôleurs:

public class TableController { 

    @FXML 
    private TableView<InputObject> tableInfo; 
    @FXML 
    private TableColumn<InputObject, String> col1; 

    public void initialize() { 
     col1.setCellValueFactory(new PropertyValueFactory<>("text")); 
    } 

    public void setTableItems(ObservableList<InputObject> tableItems) { 
     tableInfo.setItems(tableItems); 
    } 
} 

La table affiche maintenant le contenu de la liste items créée dans la méthode initalize() du contrôleur principal et la référence InputController dans la même liste. Donc, tout ce que vous devez faire est de mettre à jour cette liste dans le InputController. Je suppose que vous voulez juste ajouter des éléments à la table (les remplacer pas tous):

public class InputController { 

    @FXML 
    private TextArea inputArea; 
    @FXML 
    private Button inputButton; 

    private ObservableList<InputObject> tableItems ; 

    public void setTableItems(ObservableList<InputObject> tableItems) { 
     this.tableItems = tableItems ; 
    } 

    public void inputToTable() { 
     if(! inputArea.getText().isEmpty()) { 
      tableItems.add(new InputObject(inputArea.getText())); 
     } 
    } 


} 

Plus généralement, si vous avez plus de données à partager entre les différents contrôleurs, vous devez créer une ou plusieurs classes « modèles » et partager une instance de modèle avec les contrôleurs. Ensuite, vous pouvez observer les propriétés du modèle et les mettre à jour. Voir Applying MVC With JavaFx pour un exemple plus complet.