Захват значений из текстового поля в ячейке таблицы

#java #javafx #textarea #tableview #enumeration

#java #javafx #текстовое поле #просмотр таблицы #перечисление

Вопрос:

Сценарий: Я передаю значения, разделенные запятыми, в таблицу. 2 столбца, один с исходным значением, другой с текстовым полем со значениями, заполненными внутри. Они выстроены в ряд, чтобы я мог добавлять / изменять значения и копировать изменения в строку.

Я не могу понять, как захватить данные текстового поля после того, как они помещены в таблицу. Приведенный ниже код:

Главная:

 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();
        }
    }
}
  

Контроллер:

 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>
  

Любая помощь была бы высоко оценена.

Ответ №1:

Я не уверен точно, что они пытаются сделать, но я нашел способ получить TextField , когда они нажимают enter.

В вашем TextFieldCell классе я добавил setOnAction , чтобы захватить то, что пользователь вводит в TextField .

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

Вы можете использовать это вместо кнопки, чтобы делать с введенным текстом все, что захотите.

Я понятия не имею, как использовать вашу кнопку, чтобы программно захватить все TextField in col2 и захватить их текст.

Но с setOnAction вы можете добавлять туда все, что вам нравится, и, надеюсь, делать то, что вам нужно.

Редактировать 1 После некоторого интенсивного редактирования вашей работы я сделал это! Я оставлю старый ответ, поскольку он применим непосредственно к вашему исходному коду.

Сначала я сделал col2 так.

 @FXML public TableColumn<tableClass, TextField> col2;
  

Затем я использовал это в своих интересах и setCellValueFactory вот так:

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

Все, что связано с col2 , мне пришлось обновить / удалить, чтобы заставить его работать с TextField , и в итоге я получил гораздо более короткий исходный код, который может делать то, что вы хотите. Пример находится в captureText методе.
Я отредактировал tableClass , чтобы использовать TextField , я полностью удалил ваш cellFactory класс. Надеюсь, это поможет.

 @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
  

Комментарии:

1. Целью событий captureText action является захват всех текстовых полей и объединение их в одну строку. Я попробую то, что вы придумали. Спасибо!

2. Да, я так и думал, к сожалению, я не смог найти способ захватить их все. Может быть, кто-то еще может.

3. Я заставил это работать, но мне пришлось сильно модифицировать ваш код.

4. Потрясающе! отлично работает. Я знаю, что мой код был неаккуратным. Я собрал это очень быстро. я ценю вашу помощь.