2017-05-21 1 views
1

Je développe une application en JavaFx dans laquelle j'ai deux onglets.JavaFx: Comment implémenter un Gridpane dynamique?

En premier onglet, j'ai ComboBox:

enter image description here

Dans Second Tab j'ai Gridpane comme ceci:

enter image description here

Ce que je veux est quand choisir l'utilisateur laisser dire 3 de la liste déroulante de l'onglet A comme:

enter image description here

Il devrait ajouter 3 lignes à la grille de l'onglet B et chaque colonne avec champs de texte, cases à cocher et datepicker. Colonne A ayant Zones de texte, colonne B ayant cases à cocher et la colonne C ayant DatePicker comme ceci:

enter image description here

S'il vous plaît aidez-moi comment puis-je parvenir et après avoir obtenu comment puis-je accéder aux données de chaque textField, cases à cocher et datepicker .

Mise à jour: Essayer de faire solution @Yahya avec FXML

Main.java

public class Main extends Application { 
    @Override 
    public void start(Stage primaryStage) { 
     try { 
      TabPane root = (TabPane)FXMLLoader.load(getClass().getResource("Sample.fxml")); 
      Scene scene = new Scene(root,400,400); 
      scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

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

SampleController.java

public class SampleController { 

    @FXML 
    private TabPane root ; 
    @FXML 
    private Tab tabA ; 
    @FXML 
    private Tab tabB ; 
    @FXML 
    private ComboBox<Integer> comboBox ; 
    @FXML 
    private static GridPane gridPane ; 
    @FXML 
    private AnchorPane anchB ; 


public void initialize() { 

    // Create a comboBox, set its attributes and add it to container 
    comboBox.getItems().addAll(1,2,3,4,5,6,7,8,9,10); 
    comboBox.setValue(1); 
    comboBox.setEditable(false); 
    // anchA.getChildren().add(comboBox); 

    // add listener to tabPane 
    root.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>(){ 
     @Override 
     public void changed(ObservableValue<? extends Tab> observable, Tab oldTab, Tab newTab){ 
       if(newTab == tabB) { // when tabB is selected 
        System.out.println(anchB.getChildren().size()); 
        if(anchB.getChildren().size()<=0){ // if already contains a table 

         anchB.getChildren().add(table(comboBox.getValue())); 

         table(comboBox.getValue()); 
         System.out.println("hello"); 
        } 
        else { 
        anchB.getChildren().remove(gridPane); // remove it 
        System.out.println("no"); 
        } 
      } 
     } 
    }); 
} 

//This static method shall create the table dynamically when it's called 
// you can add, change and remove the attributes of the table components 
// the colors and all other decoration(e.g. position) are for example 
public static GridPane table(int rows){ 

    for(int i=0; i<rows; i++){ 
     TextField textField = new TextField(); 
     textField.setAlignment(Pos.CENTER); 
     CheckBox checkBox = new CheckBox("Check Box"); 
     checkBox.setTextFill(Color.WHITE); 
     checkBox.setAlignment(Pos.CENTER); 
     DatePicker datePicker = new DatePicker(); 

     //add them to the GridPane 
     gridPane.add(textField, 0, i+1); // (child, columnIndex, rowIndex) 
     gridPane.add(checkBox , 1, i+1); 
     gridPane.add(datePicker,2, i+1); 

     // margins are up to your preference 
     GridPane.setMargin(textField, new Insets(5)); 
     GridPane.setMargin(checkBox, new Insets(5)); 
     GridPane.setMargin(datePicker, new Insets(5)); 
    } 

    return gridPane; 

} 
} 

Sample.FXML

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

<?import javafx.scene.control.ComboBox?> 
<?import javafx.scene.control.Tab?> 
<?import javafx.scene.control.TabPane?> 
<?import javafx.scene.layout.AnchorPane?> 
<?import javafx.scene.layout.ColumnConstraints?> 
<?import javafx.scene.layout.GridPane?> 
<?import javafx.scene.layout.RowConstraints?> 
<?import javafx.scene.text.Text?> 

<TabPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" tabClosingPolicy="UNAVAILABLE" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SampleController"> 
    <tabs> 
     <Tab fx:id="tabA" text="Tab A"> 
     <content> 
      <AnchorPane fx:id="anchA" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0"> 
       <children> 
        <ComboBox fx:id="comboBox" layoutX="225.0" layoutY="82.0" prefWidth="150.0" /> 
       </children> 
      </AnchorPane> 
     </content> 
     </Tab> 
     <Tab fx:id="tabB" text="Tab B"> 
     <content> 
      <AnchorPane fx:id="anchB" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0"> 
       <children> 
        <GridPane fx:id="gridPane" gridLinesVisible="true" layoutX="150.0" layoutY="62.0"> 
        <columnConstraints> 
         <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> 
         <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> 
         <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> 
        </columnConstraints> 
        <rowConstraints> 
         <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> 
        </rowConstraints> 
        <children> 
         <Text strokeType="OUTSIDE" strokeWidth="0.0" text="A" textAlignment="CENTER" wrappingWidth="91.67529296875" /> 
         <Text strokeType="OUTSIDE" strokeWidth="0.0" text="B" textAlignment="CENTER" wrappingWidth="93.5986328125" GridPane.columnIndex="1" /> 
         <Text strokeType="OUTSIDE" strokeWidth="0.0" text="C" textAlignment="CENTER" wrappingWidth="95.287109375" GridPane.columnIndex="2" /> 
        </children> 
        </GridPane> 
       </children> 
      </AnchorPane> 
     </content> 
     </Tab> 
    </tabs> 
</TabPane> 

Répondre

1

Vous pouvez faire quelque chose comme ceci:

import javafx.application.Application; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.CheckBox; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.DatePicker; 
import javafx.scene.control.Tab; 
import javafx.scene.control.TabPane; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.Background; 
import javafx.scene.layout.BackgroundFill; 
import javafx.scene.layout.GridPane; 
import javafx.scene.layout.Pane; 
import javafx.scene.layout.StackPane; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 

public class DynamicTable extends Application{ 

    @Override 
    public void start(Stage ps) throws Exception { 

     // Create a Tab A, create a container and add it 
     Tab tabA = new Tab("Tab A"); 
     StackPane containerA = new StackPane(); 

     // note that the colors are for example 
     containerA.setBackground(new Background(
       new BackgroundFill(Color.MAROON,null,null))); 
     // Create a comboBox, set its attributes and add it to container 
     ComboBox<Integer> comboBox = new ComboBox<Integer>(); 
     comboBox.getItems().addAll(1,2,3,4,5,6,7,8,9,10); 
     comboBox.setValue(1); 
     comboBox.setEditable(false); 
     containerA.getChildren().add(comboBox); 

     //add the container to the tabA 
     tabA.setContent(containerA); 

     // Create Tab B, create a container and add it 
     Tab tabB = new Tab("Tab B"); 
     StackPane containerB = new StackPane(); 

     containerB.setBackground(new Background(
         new BackgroundFill(Color.DARKMAGENTA,null,null))); 
     tabB.setContent(containerB); 
     // create TabPane and add the Tabs to it 
     // all other values need manipulation (i.e. up to your preference) 
     TabPane tabPane = new TabPane(); 
     tabPane.getTabs().addAll(tabA, tabB); 
     //set size and other attributes (if any), for example 
     tabPane.setMinWidth(500); 
     tabPane.setMinHeight(500); 

     // add listener to tabPane 
     tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>(){ 
       @Override 
       public void changed(ObservableValue<? extends Tab> observable, Tab oldTab, Tab newTab){ 
        if(newTab == tabB) { // when tabB is selected 
         if(containerB.getChildren().size()>0){ // if already contains a table 
          containerB.getChildren().remove(0); // remove it 
         } 
         containerB.getChildren().add(table(comboBox.getValue())); // create the table and add it 
       } 
      } 
     }); 

     // simple root to test 
     Pane root = new Pane(); 
     root.getChildren().add(tabPane); 

     Scene scene = new Scene(root, 500,500); 
     ps.setScene(scene); 
     ps.setTitle("Dynamic Table In Tab"); 
     ps.show(); 
    } 


    // This static method shall create the table dynamically when it's called 
    // you can add, change and remove the attributes of the table components 
    // the colors and all other decoration(e.g. position) are for example 
    public static GridPane table(int rows){ 
     GridPane table = new GridPane(); 

     for(int i=0; i<rows; i++){ 
      TextField textField = new TextField(); 
      textField.setAlignment(Pos.CENTER); 
      CheckBox checkBox = new CheckBox("Check Box"); 
      checkBox.setTextFill(Color.WHITE); 
      checkBox.setAlignment(Pos.CENTER); 
      DatePicker datePicker = new DatePicker(); 

      //add them to the GridPane 
      table.add(textField, 0, i); // (child, columnIndex, rowIndex) 
      table.add(checkBox , 1, i); 
      table.add(datePicker,2, i); 

      // margins are up to your preference 
      GridPane.setMargin(textField, new Insets(5)); 
      GridPane.setMargin(checkBox, new Insets(5)); 
      GridPane.setMargin(datePicker, new Insets(5)); 
     } 
     table.setAlignment(Pos.CENTER); 

     return table; 

    } 

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

    } 
} 

test

enter image description here

enter image description here

Mise à jour : Si vous souhaitez obtenir les valeurs de la table dans TabB, vous pouvez faire quelque chose comme ceci:

// first create a method like this 
// this static method to return a component from Table at specific row and column 
public static Node getComponent (int row, int column, GridPane table) { 
    for (Node component : table.getChildren()) { // loop through every node in the table 
     if(GridPane.getRowIndex(component) == row && 
         GridPane.getColumnIndex(component) == column) { 
      return component; 
     } 
    } 

    return null; 
} 

// Then use the method like this 
// The textfield always at Column 0, check box column 1 and Date picker 2 
// and the GridPane is in a StackPane(container) at index 0 
// Note that you may NEED to add a button and wrap the following code with its Action Listener (i.e. button.setOnAction()) 
if(containerB.getChildren().size()>0){ // that means it contains a table  
    GridPane table = (GridPane) containerB.getChildren().get(0); 
    for(int i=0 ; i<comboBox.getValue(); i++){ 
     String Text = ((TextField)getComponent (i, 0, table)).getText(); 
     boolean selected = ((CheckBox)getComponent (i, 1, table)).isSelected(); 
     LocalDate date = ((DatePicker)getComponent (i, 2, table)).getValue(); 

     System.out.println(Text + " " + selected + " " + date); 
     System.out.println("Next Row"); 
    } 

} 

MISE À JOUR:

Si vous voulez que votre programme pour supprimer/créer la table (GridPane) que si l'utilisateur a modifié la valeur ComboBox, alors vous devez ajouter un ChangeListener à votre ComboBox pour attraper les changements, vous devez par conséquent par exemple un global boolean qui chan gements de true à false et vice versa lorsque la valeur change ComboBox, et ce boolean à vérifier dans le if-statement qui vérifie si la table existe déjà dans containerB (dans votre question mise à jour anchB), par exemple quelque chose comme ceci:

boolean valueChanged = false; // its scope should be global and to be added to the ComboBox ChangeListener 
if(containerB.getChildren().size()>0 && valueChanged){ // if already contains a table 
    containerB.getChildren().remove(0); // remove it 
} 
+0

Merci pour votre réponse @Yahya, pouvez-vous s'il vous plaît me dire comment puis-je y parvenir si j'ai construit l'interface utilisateur en utilisant FXML? – Junaid

+0

@Junaid Vous auriez dû mentionner cela dans votre question, Cependant, j'ai créé un programme complet pour votre question, si c'est d'aide, veuillez l'accepter. En ce qui concerne les composants dans le 'FXML', donnez chacun un' id', puis utilisez la méthode de recherche http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html# lookup-java.lang.String- – Yahya

+0

Je suis capable de le faire avec FXML mais le problème est que je ne suis pas en mesure d'enlever Gridpane il lance "Exception dans le fil" JavaFX Application Thread "java.lang.NullPointerException". – Junaid