0

Scenario: Im passing in comma separated values to a table. 2 columns, one with the original value, one with a text field with the values populated inside. They are lined up so I can add/change values, and copy the changes to a string.

I cannot figure out how to capture the TextField data after they are put in the table. Code below:

Main:

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

public class Main extends Application {


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

    @Override
    public void start(Stage primaryStage) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("/application/MainFxml.fxml")); //this is the file that 
            Scene scene = new Scene(root,800,800); ////100,100 is width and height of window
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

Controller:

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.ResourceBundle;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;

public class MainFxmlController implements Initializable {

    public static int count=-1;

    @FXML public TableView<tableClass> table = new TableView<tableClass>();
    @FXML private TableColumn<tableClass, String>col1;
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @FXML public TableColumn<tableClass, Row> col2 = new TableColumn("Row");

    @FXML public TextField txt;
    @FXML public Button btn, btn2;
    @FXML public ListView<String> listView = new ListView<String>();
    public static ArrayList<String> input = new ArrayList<String>();

    final HBox hb = new HBox();
    public ObservableList<tableClass> obList = FXCollections.observableArrayList();  // each column contains an observable list object 
    public ObservableList<tableClass> loadTable(){
        return obList;   //return data object
    }////END loadData


    @Override
    public void initialize(URL url, ResourceBundle rb) {
            table.setEditable(true);
            col1.setCellValueFactory(cellData -> cellData.getValue().getCol1());  


            col2.setCellFactory((param) -> new TextFieldCell<tableClass, Row>(EnumSet.allOf(Row.class)));
            col2.setCellValueFactory(new PropertyValueFactory<tableClass, Row>("Row"));
            col2.setOnEditCommit(
                    new EventHandler<CellEditEvent<tableClass, Row>>() {
                        @Override
                        public void handle(CellEditEvent<tableClass, Row> t) {
                            ((tableClass) t.getTableView().getItems().get(
                                t.getTablePosition().getRow())
                                ).setCol2(t.getNewValue());
                        }
                    }
                );

            tableClass Entry = new tableClass(" ", Row.Row1); //create the table using getters/setters from Table Class
            table.getItems().addAll(Entry);         
            table.setItems(loadTable());

            col1.setCellFactory(TextFieldTableCell.<tableClass>forTableColumn()); //Makes the columns themselves editable
            col1.setOnEditCommit(
                    new EventHandler<CellEditEvent<tableClass, String>>() {
                        @Override
                        public void handle(CellEditEvent<tableClass, String> t) {
                            ((tableClass) t.getTableView().getItems().get( t.getTablePosition().getRow())).setCol1(t.getNewValue());
                        }              
                    }
                    );
            col1.setStyle( "-fx-alignment: BOTTOM-RIGHT;"); //to alight text next to textArea

            txt.setText("fsad,0,0,gfds,43,4,4,fdsg,rtewrtwe,0,67,3,4,4,,4,44,,4");  //TO BE ROMOVED UPON COMPLETION

    }//end initialize

    public void buttonAction(ActionEvent e){
        if(txt.getText() != ""){
            System.out.println(txt.getText());
            ArrayList<String> myList = new ArrayList<String>(Arrays.asList(txt.getText().split(",")));
            input = myList;     
        }

        for(int i =0; i< input.size(); i++){
            Row.Row1.equals(input.get(i).toString());
            obList.add(new tableClass(input.get(i).toString(), Row.Row1));
        }//end for

    }//end buttonAction


    public void captureText(ActionEvent e){

        /*
         * HERE I NEED TO CAPTURE VALUES FROM THE TEXT FIELDS
         * IN COL2
         */

    }



    public static enum Row { //enum for the dxTable radio button  if you want any other options, add another value and another radio buttton will be populated
        Row1;
    }


    public static class TextFieldCell<S,T extends Enum<T>> extends TableCell<S,T>{

        private EnumSet<T> enumeration;

        public TextFieldCell(EnumSet<T> enumeration) {
            this.enumeration = enumeration;
        }

        @Override
        protected void updateItem(T item, boolean empty)
        {
            super.updateItem(item, empty);
            if (!empty) 
            {
                // gui setup
                HBox hb = new HBox(7);
                hb.setAlignment(Pos.CENTER);


                // create a radio button for each 'element' of the enumeration
                for (Enum<T> enumElement : enumeration) {
                        try{
                        TextField textField = new TextField(input.get(count));
                        textField.setUserData(enumElement);
                        hb.getChildren().add(textField);
                        }catch(IndexOutOfBoundsException e){}
                }

                // issue events on change of the selected radio button

                setGraphic(hb);
                count++;
            } //end if
            else
                setGraphic(null);
        }//updateItem
    }//END TextFieldCell class


    public static class tableClass{              ///table object with getters and setters.
        public final SimpleStringProperty col1;
        public final SimpleObjectProperty<Row> col2 = new SimpleObjectProperty<Row>();      

        public tableClass(String col1, Row t) {   //uses an enum for the second type
          this.col1 = new SimpleStringProperty(col1);
          this.col2.setValue(t);
        }

        public StringProperty getCol1() {
            return col1;
        }

        public void setCol1(String i) {
            col1.set(i);
        }

        public void setCol2(Row t) {
            col2.set(t);
        }       

        public Row getCol2() {
            return col2.get();
        }
        public String getCol2(int index) {

            return "";
        }

      }//end table class
}//end controller

FXML:

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="800.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainFxmlController">
   <children>
      <Button fx:id="btn" layoutX="723.0" layoutY="26.0" mnemonicParsing="false" onAction="#buttonAction" text="btn" />
      <TextField fx:id="txt" layoutX="41.0" layoutY="26.0" prefHeight="25.0" prefWidth="647.0" />
      <TableView fx:id="table" editable="true" layoutX="41.0" layoutY="106.0" prefHeight="588.0" prefWidth="451.0">
        <columns>
          <TableColumn fx:id="col1" prefWidth="75.0" text="C1" />
          <TableColumn fx:id="col2" prefWidth="114.0" text="C2" />
        </columns>
      </TableView>
      <Button fx:id="btn2" layoutX="507.0" layoutY="669.0" mnemonicParsing="false" onAction="#captureText" text="Button" />
   </children>
</AnchorPane>

Any help would be greatly appreciated.

Nevets17
  • 109
  • 1
  • 9

1 Answers1

1

I'm not sure exactly what are trying to do, but I have found a way to get the TextField when they press enter.

In your TextFieldCell class, I added a setOnAction to grab what the user input in the TextField.

TextField textField = new TextField(input.get(count));
textField.setUserData(enumElement);
textField.setOnAction(event -> {
   System.out.println("Gotcha");
});

You can use that, instead of the button, to do whatever you want to the text entered.

I have no idea how to use your button to programmatically grab all of the TextField in col2 and grab their text.

But, with the setOnAction you can add whatever you like in there and hopefully do what you need to do.

Edit 1 With some heavy editing of your work, I have done it! I will leave in the old answer, since it applies directly to your source code.

First, I made col2 Look like this.

@FXML public TableColumn<tableClass, TextField> col2;

Then, I used that to my advantage and setCellValueFactory like so:

col2.setCellValueFactory(new PropertyValueFactory<>("col2"));

Everything to do with col2 I had to update/remove to get it to work with the TextField, and I ended up with a much shorter source code, that can do what you want. Example is in the captureText method. I edited the tableClass to make use of the TextField, I removed your cellFactory class altogether. Hope this helps.

@FXML public TableView<tableClass> table;
@FXML private TableColumn<tableClass, String>col1;
@SuppressWarnings({ "unchecked", "rawtypes" })
@FXML public TableColumn<tableClass, TextField> col2;

@FXML public TextField txt;
@FXML public Button btn, btn2;
public static ArrayList<String> input = new ArrayList<String>();

public static Group hb = new Group();
public ObservableList<tableClass> obList = FXCollections.observableArrayList();  // each column contains an observable list object
public ObservableList<tableClass> loadTable(){
    return obList;   //return data object
}////END loadData


@Override
public void initialize(URL url, ResourceBundle rb) {
    table.setEditable(true);
    col1.setCellValueFactory(cellData -> cellData.getValue().col1Property());


    col2.setCellValueFactory(new PropertyValueFactory<>("col2"));

    table.setItems(loadTable());

    col1.setCellFactory(TextFieldTableCell.<tableClass>forTableColumn()); //Makes the columns themselves editable
    col1.setOnEditCommit(
            new EventHandler<CellEditEvent<tableClass, String>>() {
                @Override
                public void handle(CellEditEvent<tableClass, String> t) {
                    ((tableClass) t.getTableView().getItems().get( t.getTablePosition().getRow())).setCol1(t.getNewValue());
                }
            }
    );
    col1.setStyle( "-fx-alignment: BOTTOM-RIGHT;"); //to alight text next to textArea

    txt.setText("fsad,0,0,gfds,43,4,4,fdsg,rtewrtwe,0,67,3,4,4,,4,44,,4");  //TO BE ROMOVED UPON COMPLETION

}//end initialize

public void buttonAction(ActionEvent e){
    if(txt.getText() != ""){
        System.out.println(txt.getText());
        ArrayList<String> myList = new ArrayList<String>(Arrays.asList(txt.getText().split(",")));
        input = myList;
    }

    for(int i =0; i< input.size(); i++){
        obList.add(new tableClass(input.get(i),input.get(i)));
    }//end for

}//end buttonAction


public void captureText(ActionEvent e) {
    obList.forEach(event -> {
        event.setCol1(event.getCol2().getText());
    });
    /*
     * HERE I NEED TO CAPTURE VALUES FROM THE TEXT FIELDS
     * IN COL2
     */
}


public static class tableClass{              ///table object with getters and setters.
    public final SimpleStringProperty col1;
    public final TextField col2;

    public tableClass(String col1, String col2) {   //uses an enum for the second type
        this.col1 = new SimpleStringProperty(col1);
        this.col2 = new TextField(col2);
    }

    public StringProperty col1Property() {
        return col1;
    }
    public String getCol1(){
        return col1.get();
    }

    public void setCol1(String i) {
        col1.set(i);
    }

    public void setCol2(String tx) {
        col2.setText(tx);
    }

    public TextField getCol2() {
        return col2;
    }

}//end table class
Hypnic Jerk
  • 1,192
  • 3
  • 14
  • 32