Проблема с полем со списком и наблюдаемым кодом списка

Извините, если мой английский не настолько хорош, насколько это возможно, но я француз, и мне действительно нужна помощь в решении проблемы с моим кодом. Объяснение: я хочу поместить 3 значения в свой наблюдаемый список из 1 поля со списком и 2 текстовых полей. Текст текстовых полей получался, но поскольку я создаю поле со списком, в список не добавляется никакого значения. Не могли бы вы мне помочь ? (Я поставил свой код чуть ниже) :) Сердечно

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;


public class Tableviewex extends Application {

private TableView<Person> table = new TableView<>();
private ObservableList<Person> data =
        FXCollections.observableArrayList();
private ObservableList<String> listproduit = FXCollections.observableArrayList("Doliprane","Spasfon");
private Pane layout = new Pane();
private HBox hb = new HBox();

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

@Override
public void start(Stage stage) {
    Scene scene = new Scene(new Group());
    stage.setTitle("Table View Sample");
    stage.setWidth(450);
    stage.setHeight(550);

    final Label label = new Label("Choisissez vos médicaments");
    label.setFont(new Font("Arial", 20));

    table.setEditable(true);

    TableColumn<Person, String> produitcol = 
        new TableColumn<>("Produit");
    produitcol.setMinWidth(100);
    produitcol.setCellValueFactory(
        new PropertyValueFactory<>("produit"));



   produitcol.setCellFactory(TextFieldTableCell.<Person>forTableColumn());
    produitcol.setOnEditCommit(
        (CellEditEvent<Person, String> t) -> {
            ((Person) t.getTableView().getItems().get(
                t.getTablePosition().getRow())
                ).setFirstName(t.getNewValue());
    });


    TableColumn<Person, String> lastNameCol = 
        new TableColumn<>("Quantité");
    lastNameCol.setMinWidth(100);
    lastNameCol.setCellValueFactory(
        new PropertyValueFactory<>("quantité"));
   lastNameCol.setCellFactory(TextFieldTableCell.<Person>forTableColumn());
   lastNameCol.setOnEditCommit(
        (CellEditEvent<Person, String> t) -> {
            ((Person) t.getTableView().getItems().get(
                    t.getTablePosition().getRow())
                    ).setLastName(t.getNewValue());
    });

    TableColumn<Person, String> emailCol = new TableColumn<>("Prix");
    emailCol.setMinWidth(200);
    emailCol.setCellValueFactory(
        new PropertyValueFactory<>("prix"));
    emailCol.setCellFactory(TextFieldTableCell.<Person>forTableColumn());       
    emailCol.setOnEditCommit(
        (CellEditEvent<Person, String> t) -> {
            ((Person) t.getTableView().getItems().get(
                    t.getTablePosition().getRow())
                    ).setEmail(t.getNewValue());
    });

    table.setItems(data);
    table.getColumns().addAll(produitcol, lastNameCol, emailCol);

    final ComboBox<String> choixproduit = new ComboBox<>();
    choixproduit.setItems(listproduit);
    choixproduit.setPromptText("Choissisez votre produit");
    choixproduit.setMaxWidth(produitcol.getPrefWidth());
    final TextField addLastName = new TextField();
    addLastName.setMaxWidth(lastNameCol.getPrefWidth());
    addLastName.setPromptText("Quantité");
    final TextField addEmail = new TextField();
    addEmail.setMaxWidth(emailCol.getPrefWidth());
    addEmail.setPromptText("Prix");

    final Button addButton = new Button("Ajouter");
    addButton.setOnAction((ActionEvent e) -> {
        data.add(new Person(
                choixproduit.getValue(),
                addLastName.getText(),
                addEmail.getText()));
        //addFirstName.clear();
        addLastName.clear();
        addEmail.clear();
    });

    hb.getChildren().addAll(choixproduit, addLastName, addEmail, addButton);
    hb.setSpacing(3);

    final VBox vbox = new VBox();
    vbox.setSpacing(5);
    vbox.setPadding(new Insets(10, 0, 0, 10));
    vbox.getChildren().addAll(label, table, hb);

    ((Group) scene.getRoot()).getChildren().addAll(vbox);
    layout.setStyle("-fx-background-color: linear-gradient(to top, #24B400, #FFFFFF)");

    stage.setScene(scene);
    stage.show();
}

public static class Person {

    private final SimpleStringProperty produit;
    private final SimpleStringProperty quantité;
    private final SimpleStringProperty prix;

    private Person(String fName, String lName, String email) {
        this.produit = new SimpleStringProperty(fName);
        this.quantité = new SimpleStringProperty(lName);
        this.prix = new SimpleStringProperty(email);
    }

    public String getFirstName() {
        return produit.get();
    }

    public void setFirstName(String fName) {
        produit.set(fName);
    }

    public String getLastName() {
        return quantité.get();
    }

    public void setLastName(String fName) {
        quantité.set(fName);
    }

    public String getEmail() {
        return prix.get();
    }

    public void setEmail(String fName) {
        prix.set(fName);
    }
}

}


person Alexis Ouvrard Ragot    schedule 26.03.2019    source источник
comment
ваша таблица настроена неправильно - пожалуйста, прочитайте API-документ PropertyValueFactory   -  person kleopatra    schedule 26.03.2019
comment
Ваша проблема именно в том, на что указывает @kleopatra. Я предполагаю, что вы начинаете с этого руководства и изменяете его для медицинской цели, но вы делаете только половину (человек =/= лекарство, ваши геттеры и сеттеры плохо названы, так как вы переименовали атрибут, и это важно для StringProperty и для того, чтобы сделать ваш код понятным).   -  person Pagbo    schedule 26.03.2019
comment
Кроме того, я не уверен, что вы хотите сохранить CellFactory для produitcol как TextFieldTableCell (даже если это не запрещено, по крайней мере, вы должны добавить введенное лекарство в свой список лекарств listproduit). И самое главное, не используйте акцент для программирования и по возможности пишите свой код на английском языке (например, quantityquantitequantité)   -  person Pagbo    schedule 26.03.2019
comment
Спасибо всем за ваши ответы. Извините за французский код, я постараюсь обновить его на английском для вас! Кстати, я новичок в программировании на Java, и я не совсем понимаю, что мне нужно изменить в моем коде, не могли бы вы помочь мне в другой раз? Большое спасибо   -  person Alexis Ouvrard Ragot    schedule 26.03.2019
comment
В Java есть нечто, называемое Java Bean (это просто шаблон, а не часть языка). В этом шаблоне свойства являются закрытыми полями (например, name), и вы получаете доступ к этому свойству с помощью геттера (например, getName()) и необязательного сеттера (например, setName(<object-type>)). Сеттер необходим только для записываемых свойств. Заметили шаблон в именах методов? Это get<property-name> и set<property-name> с использованием camelCase. Многие фреймворки Java полагаются на это соглашение. Ваш код не соответствует этому.   -  person Slaw    schedule 26.03.2019
comment
Однако JavaFX расширяет это соглашение до так называемого JavaFX Bean. Единственная разница здесь в том, что приватное поле теперь является экземпляром ReadOnlyProperty (от которого расширяется Property), и есть дополнительный метод получения свойства (например, nameProperty()), который возвращает указанное [ReadOnly]Property. Соглашение об именах здесь <property-name>Property, опять же с использованием camelCase. PropertyValueFactory опирается на шаблон Java Bean/JavaFX Bean. Поэтому, когда вы даете ему свойство (например, имя), он ищет соответствующие методы. Прочтите документы для получения дополнительной информации.   -  person Slaw    schedule 26.03.2019