Javafx 带单元格编辑的TableView

Javafx 带单元格编辑的TableView,javafx,javafx-2,tableview,tablecell,Javafx,Javafx 2,Tableview,Tablecell,我需要一个具有编辑功能的TableView 因此,我已经尝试了一点,并整理了以下代码,这些代码似乎对我来说很好——直到我开始使用更多的数据行进行测试 问题:TableView不能一次初始化所有人员/行,只能初始化进入视图的人员/行;将行移出并再次移入视图会重新初始化其内容 能否强制TableView一次加载并保留所有可用数据?我不会有超过200-300行,所以没有内存问题。还是有更好的方法 我已经尝试了标准的Oracle EditingCell示例,并对其进行了一些修改,但我无法想象在分发应用程

我需要一个具有编辑功能的TableView

因此,我已经尝试了一点,并整理了以下代码,这些代码似乎对我来说很好——直到我开始使用更多的数据行进行测试

问题:TableView不能一次初始化所有人员/行,只能初始化进入视图的人员/行;将行移出并再次移入视图会重新初始化其内容

能否强制TableView一次加载并保留所有可用数据?我不会有超过200-300行,所以没有内存问题。还是有更好的方法

我已经尝试了标准的Oracle EditingCell示例,并对其进行了一些修改,但我无法想象在分发应用程序时,用户需要在输入文本之前四次单击一个字段(然后再次四次单击下一个字段)

以下是单个类中的代码:

package config_V1;

import java.util.Vector;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.scene.Scene;

/**
 * 
 * Standard person table in a self running application <br>
 * - some configurable textField derivatives within<br>
 * - Person class within
 * 
 * - unfortunately not working as expected: 
 *      first row gets initialised always twice
 *      fields not in view are not initialised
 *      the same row gets initialised again whenever coming in view during scrolling
 *      issues with sorting (after sorting changing age updates the wrong row)
 *       this can be circumvented with setSortable(false) on each column;
 *      
 */
public class TestCustomCellFactories extends Application  {

    private Vector<Person> persons;
    private TableView <Object>tableView = new TableView<Object>();
    private ObservableList<Object> tableData = FXCollections.observableArrayList(); 
    private static Vector<TextField> textFields=new Vector<TextField>();
    private CheckBox focusFirstNameCB;
    Button addButton = new Button("Add Rows");
    Button removeButton= new Button("Remove Rows");
    Button defaultButton= new Button("set defaults");


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

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void start(Stage stage) {



        //***********   CREATE COLUMNS *****************************************
        tableView.setEditable(true);

        TableColumn firstNameCol = new TableColumn<Object,String>("First Name");
        firstNameCol.setCellFactory(makeEditableStringCellFactory(0,0));
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("firstName"));

        TableColumn lastNameCol = new TableColumn<Object,String>("Last Name");
        lastNameCol.setCellFactory(makeEditableStringCellFactory(3,1));
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("lastName"));

        TableColumn emailCol = new TableColumn<Object,String>("Email");
        emailCol.setCellFactory(makeEditableStringCellFactory(1,2));
        emailCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("email"));
        emailCol.setMinWidth(200);


        TableColumn age = new TableColumn<Object,String>("age");
        age.setCellFactory(makeEditableStringCellFactory(2,3));
        age.setCellValueFactory(
                new PropertyValueFactory<Person, String>("age"));

        TableColumn ageMinus5 = new TableColumn<Object,String>("real age");
        ageMinus5.setCellFactory(makeEditableStringCellFactory(2,4));
        ageMinus5.setCellValueFactory(
                new PropertyValueFactory<Person, String>("realAge"));





        //************* ADD EVENT HANDLER TO BUTTONS ****************************

        focusFirstNameCB= new CheckBox("focus column 1");
        focusFirstNameCB.setSelected(true);

        addButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                //prt(Platform.isFxApplicationThread());
                if(persons==null){
                    persons = new Vector<Person>();
                    persons.add(new Person("Jacob", "Smith", "jacob.smith@example.com"));
                    persons.add(new Person("Isabella", "Johnson", "isabella.johnson@example.com"));
                    persons.add(new Person("Ethan", "Williams", "ethan.williams@example.com"));
                    persons.add(new Person("Jacob2", "Smith2", "jacob.smith@example.com"));
                    persons.add(new Person("Isabella2", "Johnson2", "isabella.johnson@example.com"));
                    persons.add(new Person("Ethan2", "Williams2", "ethan.williams@example.com"));
                    persons.add(new Person("Jacob3", "Smith3", "jacob.smith@example.com"));
                    persons.add(new Person("Isabella3", "Johnson3", "isabella.johnson@example.com"));
                    persons.add(new Person("Ethan3", "Williams3", "ethan.williams@example.com"));
                    persons.add(new Person("Jacob4", "Smith4", "jacob.smith@example.com"));
                    persons.add(new Person("Isabella4", "Johnson4", "isabella.johnson@example.com"));
                    persons.add(new Person("Ethan4", "Williams4", "ethan.williams@example.com"));
                    persons.add(new Person("Jacob5", "Smith5", "jacob.smith@example.com"));
                    persons.add(new Person("Isabella5", "Johnson5", "isabella.johnson@example.com"));
                    persons.add(new Person("Ethan5", "Williams5", "ethan.williams@example.com"));
                    persons.add(new Person("Jacob6", "Smith6", "jacob.smith@example.com"));
                    persons.add(new Person("Isabella6", "Johnson6", "isabella.johnson@example.com"));
                    persons.add(new Person("Ethan6", "Williams6", "ethan.williams@example.com"));

                }
                tableView.setItems(tableData);
                for(Person p:persons){
                    if(!p.isOnTable) tableData.add(p);
                    p.isOnTable=true;
                }

                updateFocus();//does not work here
            }
        });
        removeButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                for(Person person: persons){
                    person.updatePerson();
                    prt(person.getFirstName()+";"+person.getLastName()+";" + person.getEmail() + ";" + person.getAge() + ";" + person.getRealAge());
                    tableData.remove(person);   //or tableView.getItems().remove(p);
                    person.isOnTable=false;
                }
            }
        });

        defaultButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {

                for(Person person: persons){
                    prt("default for " + person.getEmail() );
                    person.setFirstName("John");
                    person.setLastName("Doe");
                    //  person.setEmail("John.Doe@xy.com");
                }
            }
        });

        focusFirstNameCB.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                for(TextField tf:textFields){
                    if(tf.getId().equals("0"))tf.setFocusTraversable(focusFirstNameCB.isSelected());
                }
            }
        });




        //***********   ASSEMBLE GUI *****************************************  

        Scene scene = new Scene(new StackPane());
        stage.setTitle("Table View Sample");
        stage.setWidth(550);
        stage.setHeight(500);
        tableView.getColumns().addAll(firstNameCol, lastNameCol, emailCol, age, ageMinus5);
        StackPane sp= new StackPane();
        sp.getChildren().add(tableView);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(5, 5, 5, 5));
        vbox.getChildren().addAll( addButton,removeButton,defaultButton,focusFirstNameCB,sp);
        VBox.setVgrow(sp, Priority.ALWAYS);

        ((StackPane) scene.getRoot()).getChildren().add(vbox);
        stage.setScene(scene);
        stage.show();
    }

    private void updateFocus(){
        prt(textFields.size());
        for(TextField tf:textFields){
            switch(Integer.parseInt(tf.getId())){
            case 0: tf.setFocusTraversable(focusFirstNameCB.isSelected());
            }
        }
    }




    //***********   TABLE CELL CREATION  *****************************************  

    public static Callback<TableColumn<Object, String>, TableCell<Object, String>> makeEditableStringCellFactory(final int type, final int id){

        return new Callback<TableColumn<Object,String>, TableCell<Object,String>>() {
            @Override
            public TableCell<Object, String> call(final TableColumn<Object, String> tableColumn) {
                TableCell <Object, String> cell = new TableCell<Object, String>(){
                    private boolean ini=true;
                    private TextField tf=null;
                    private Person person;

                    @Override
                    public void updateItem(String s, boolean empty)
                    {
                        super.updateItem(s, empty);
                        if (empty) {
                            if(tf!=null) setText(getString());//or once removed the textFields cannot be added again
                            else 
                            {
                                setText(null);
                                setGraphic(null);
                            }
                        }
                        else 
                            if(ini){ 
                                ini=false;
                                tableColumn.getTableView().getSelectionModel().select(getIndex());
                                person = (Person)tableColumn.getTableView().getSelectionModel().getSelectedItem();

                                switch (type){
                                case 0: {
                                    tf= new TextField();break;
                                }
                                case 1: {
                                    tf= new RightAlignedUnEditableTextField();break;
                                }
                                case 2: {
                                    tf= new IntegerTextField();break;
                                }
                                case 3: {
                                    tf= new UpperCaseTextField();
                                }
                                }
                                tf.setId(""+id);
                                person.registerTF(tf);
                                tf.setEditable(true);
                                setGraphic(tf);
                                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                                tf.setText(s);
                                this.textProperty().bindBidirectional(tf.textProperty())  ;

                                textFields.add(tf);

                            }else
                                if(tf!=null){
                                    setText(getString());
                                }
                    }
                    private String getString() {
                        return getItem() == null ? "" : getItem().toString();
                    }
                };

                return cell;
            }
        };
    }







    //************************* PERSON CLASS *****************************************************

    public static class Person {
        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;
        private final SimpleStringProperty email;
        private final SimpleStringProperty age=new SimpleStringProperty();
        private final SimpleStringProperty realAge=new SimpleStringProperty();
        private boolean isOnTable = false;
        private Vector<TextField> vtf = new Vector<TextField>();

        private Person(String fName, String lName, String email) {
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.email = new SimpleStringProperty(email);
        }

        public void setFirstName(final String s) {
            firstName.set("");
            firstName.set(s);
        }
        public void setLastName(final String s) {
            lastName.set("");
            lastName.set(s);
        }
        public void setEmail(final String s) {
            email.set("");
            email.set(s);
        }
        public void setAge(final String s) {
            age.set("");
            age.set(s);
        }
        public void setRealAge(final String s) {
            realAge.set("");
            realAge.set(s);
        }

        public String getLastName() {
            return lastName.get();
        }
        public String getFirstName() {
            return firstName.get();
        }
        public String getEmail() {
            return email.get();
        }
        public String getAge() {
            return age.get();
        }
        public String getRealAge() {
            return realAge.get();
        }


        public SimpleStringProperty lastNameProperty(){
            return lastName;
        }
        public SimpleStringProperty firstNameProperty(){
            return firstName;
        }
        public SimpleStringProperty emailProperty(){
            return email;
        }
        public SimpleStringProperty ageProperty(){
            return age;
        }
        public SimpleStringProperty realAgeProperty(){
            return realAge;
        }


        public void registerTF(TextField tf){
            prt("registered a TextField for "+ this.getFirstName());
            vtf.add(tf);
            int id=Integer.parseInt(tf.getId());

            if(id==3){
                //
                tf.textProperty().addListener(new ChangeListener<String>() {
                    @Override
                    public void changed(ObservableValue<? extends String> observable,
                            String oldValue, String newValue) {
                        if(newValue !=null && newValue.length()>1 && getFirstName().startsWith("Isabella")) {
                            setRealAge((Integer.parseInt(newValue)+5)+"");
                        }else setRealAge(newValue);

                    }
                });
            }
        }

        public void updatePerson(){  //starts with id 0!!!
            for(TextField tf:vtf){
                switch(Integer.parseInt(tf.getId())){
                case 0: setFirstName(tf.getText());
                case 1: setLastName(tf.getText());
                case 2: setEmail(tf.getText());
                case 3: setAge(tf.getText());
                case 4: setRealAge(tf.getText());
                }
            }
        }
    }


    //************************* TEXT FIELD CLASSES *****************************************************

    private static class IntegerTextField extends TextField {

        public IntegerTextField() {
            super();
            addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
                @Override
                public void handle(KeyEvent event) {
                    if(!event.getCharacter().matches("[0123456789]")){
                        event.consume();
                    }
                }
            });
        }
    }

    private static class UpperCaseTextField extends TextField {

        public UpperCaseTextField() {
            super();
            focusedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue, Boolean newPropertyValue)
                {
                    if (newPropertyValue)    {//Textfield on focus
                    }   
                    else
                        if(oldPropertyValue)    {   //Textfield out focus
                            setText(getText().trim().toUpperCase());
                            if(getText().length()>10) setText( getText().substring(0, 10));
                        }
                }
            });
        }
    }


    private static class RightAlignedUnEditableTextField extends TextField {

        public RightAlignedUnEditableTextField() {
            super();
            this.setAlignment(Pos.CENTER_RIGHT);
            this.setEditable(false);
            this.setFocusTraversable(false);
        }
    }

    private static void prt(Object o) {System.out.println(o);}
}
package-config\u V1;
导入java.util.Vector;
导入javafx.application.application;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.value.ChangeListener;
导入javafx.beans.value.observeValue;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.event.ActionEvent;
导入javafx.event.EventHandler;
导入javafx.geometry.Insets;
导入javafx.geometry.Pos;
导入javafx.scene.control.Button;
导入javafx.scene.control.CheckBox;
导入javafx.scene.control.ContentDisplay;
导入javafx.scene.control.TableCell;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TableView;
导入javafx.scene.control.TextField;
导入javafx.scene.control.cell.PropertyValueFactory;
导入javafx.scene.input.KeyEvent;
导入javafx.scene.layout.Priority;
导入javafx.scene.layout.StackPane;
导入javafx.scene.layout.VBox;
导入javafx.stage.stage;
导入javafx.util.Callback;
导入javafx.scene.scene;
/**
* 
*自运行应用程序中的标准人员表
*-在
*-个人类别 * *-不幸的是,没有按预期工作: *第一行总是初始化两次 *不在视图中的字段不会初始化 *在滚动过程中,只要出现在视图中,同一行就会再次初始化 *排序问题(排序后更改年龄更新错误行) *这可以通过在每列上设置可排序(false)来避免; * */ 公共类TestCustomCellFactorys扩展了应用程序{ 私人媒介人士; private TableView TableView=new TableView(); 私有ObservableList tableData=FXCollections.observableArrayList(); 私有静态向量textFields=新向量(); 私有复选框focusFirstNameCB; Button addButton=新建按钮(“添加行”); 按钮移除按钮=新按钮(“移除行”); 按钮默认按钮=新按钮(“设置默认值”); 公共静态void main(字符串[]args){ 发射(args); } @SuppressWarnings({“rawtypes”,“unchecked”}) 公众假期开始(阶段){ //***********创建列***************************************** tableView.setEditable(true); TableColumn firstNameCol=新的TableColumn(“名字”); firstNameCol.setCellFactory(makeEditableStringCellFactory(0,0)); firstNameCol.setCellValueFactory( 新财产价值工厂(“名字”); TableColumn lastNameCol=新的TableColumn(“姓氏”); lastNameCol.setCellFactory(makeEditableStringCellFactory(3,1)); lastNameCol.setCellValueFactory( 新财产价值工厂(“姓氏”); TableColumn emailCol=新的TableColumn(“电子邮件”); emailCol.setCellFactory(makeEditableStringCellFactory(1,2)); emailCol.setCellValueFactory( 新物业价值工厂(“电子邮件”); 设置最小宽度(200); TableColumn年龄=新TableColumn(“年龄”); 年龄:setCellFactory(makeEditableStringCellFactory(2,3)); age.setCellValueFactory( 新物业价值工厂(“年龄”); TableColumn ageMinus5=新的TableColumn(“真实年龄”); ageMinus5.setCellFactory(makeEditableStringCellFactory(2,4)); ageMinus5.setCellValueFactory( 新房产价值工厂(“realAge”); //*************将事件处理程序添加到按钮**************************** focusFirstNameCB=新复选框(“焦点列1”); focusFirstNameCB.setSelected(true); addButton.setOnAction(新的EventHandler(){ @凌驾 公共无效句柄(ActionEvent e){ //prt(Platform.isFxApplicationThread()); if(persons==null){ persons=新向量(); 添加(新的人(“雅各布”、“史密斯”、“雅各布”)。smith@example.com")); 人员。添加(新人员(“伊莎贝拉”、“约翰逊”、“伊莎贝拉”)。johnson@example.com")); 人员。添加(新人员(“Ethan”、“Williams”、“Ethan”)。williams@example.com")); 人员。添加(新人员(“Jacob2”、“Smith2”、“jacob。smith@example.com")); 人员。添加(新人员(“Isabella2”、“Johnson 2”、“isabella”)。johnson@example.com")); 人员。添加(新人员(“Ethan2”、“Williams2”、“ethan。williams@example.com")); 人员。添加(新人员(“Jacob3”、“Smith3”、“jacob。smith@example.com")); 人员。添加(新人员(“Isabella3”、“Johnson 3”、“isabella”)。johnson@example.com")); 人员。添加(新人员(“Ethan3”、“Williams3”、“ethan。williams@example.com")); 人员。添加(新人员(“Jacob4”、“Smith4”、“jacob。smith@example.com")); 人员。添加(新人员(“Isabella4”、“Johnson 4”、“isabella”)。johnson@example.com")); 人员。添加(新人员(“Ethan4”、“Williams4”、“ethan。williams@example.com")); 人员。添加(新人员(“Jacob5”、“Smith5”、“jacob。smith@example.com"));