JavaFX - 使用自定义textfield tablecell删除tableview中的行

时间:2018-05-18 00:31:42

标签: uitableview javafx tableview javafx-8

我正在实现自定义可编辑文本单元格以获取tableview中的TAB功能。一切正常,但是当我删除一行时,删除行下面的可编辑单元格会同时更改这些值。因此,键入已删除行下方的单元格将更改该列中多个单元格的项目。

Screenshot 1 - Tableview populated with initial values & row to be deleted is selected
Screenshot 2 - Tableview after deleting selected row
Screenshot 3 - The editable text cells in the rows below the deleted rows are updated simultaneously

如果我减小窗口大小,以便一次只能看到3行并点击删除按钮,那么当前视图外部的可编辑单元格的值将获得上述行为。

以下是我的代码。

主:

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

public class Main extends Application {

@Override
public void start(Stage primaryStage) throws Exception{
    Parent root = FXMLLoader.load(getClass().getResource("IndexIssueSample.fxml"));
    primaryStage.setTitle("Hello World");
    primaryStage.setScene(new Scene(root, 600, 575));
    primaryStage.show();
}


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

控制器:

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import java.net.URL;
import java.util.ResourceBundle;

public class IndexIssueController implements Initializable {
@FXML
private TableView<Person> personTableView;

@FXML
private TableColumn<Person, String> someDataColumn;

@FXML
private TableColumn<Person, String> someMoreDataColumn;

@FXML
private TableColumn<Person, String> additionalDataColumn;

Person person = new Person();

@Override
public void initialize(URL location, ResourceBundle resources) {
    someDataColumn.setCellValueFactory(new PropertyValueFactory<>("someData"));
    someMoreDataColumn.setCellValueFactory(new PropertyValueFactory<>("someMoreData"));
    ObservableList<Person> personObservableList = FXCollections.observableArrayList();
    additionalDataColumn.setCellValueFactory(new PropertyValueFactory<>("additionalData"));
    someDataColumn.setCellFactory(e -> new EditableTextCell(0));
    someMoreDataColumn.setCellFactory(e -> new EditableTextCell(1));
    Person initPerson = setUpPersonData();
    Person personData1 = null, personData2 = null, personData3 = null, personData4 = null, personData5 = null, personData6 = null;
    try {
        personData1 = (Person) initPerson.clone();
        personData2 = (Person) initPerson.clone();
        personData3 = (Person) initPerson.clone();
        personData4 = (Person) initPerson.clone();
        personData5 = (Person) initPerson.clone();
        personData6 = (Person) initPerson.clone();
        personData1.setSomeData("1");
        personData1.setSomeMoreData("a");
        personData2.setSomeData("2");
        personData2.setSomeMoreData("b");
        personData3.setSomeData("3");
        personData3.setSomeMoreData("c");
        personData4.setSomeData("4");
        personData4.setSomeMoreData("d");
        personData5.setSomeData("5");
        personData5.setSomeMoreData("e");
        personData6.setSomeData("6");
        personData6.setSomeMoreData("f");
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
    personObservableList.addAll(personData1, personData2, personData3, personData4, personData5, personData6);
    personTableView.setItems(personObservableList);
    personTableView.getSelectionModel().setCellSelectionEnabled(true);
}

private Person setUpPersonData() {
    try {
        person.setSomeData("This is SomeData");
        person.setSomeMoreData("This is SomeMoreDate");
        person.setAdditionalData("This is AdditionalData");
    } catch (Exception e1) {
        e1.printStackTrace();
    }
    return person;
}

@FXML
public void deleteRowButtonPushed(){
    personTableView.getItems().remove(personTableView.getSelectionModel().getSelectedItem());
}
}

自定义可编辑文本单元格:

import javafx.collections.ObservableList;
import javafx.scene.control.*;

class EditableTextCell extends TableCell<Person, String> {
private final TextField textField;
    EditableTextCell(int columnIndex) {

        textField = new TextField();

        this.indexProperty().addListener((obs, oldValue, newValue) -> {
                ObservableList<Person> tableData = getTableView().getItems();
                int oldIndex = oldValue.intValue();
                if (oldIndex >= 0 && oldIndex < tableData.size()) {
                    if (columnIndex == 0)
                        textField.textProperty().unbindBidirectional(tableData.get(oldIndex).someDataProperty());
                    if (columnIndex == 1)
                        textField.textProperty().unbindBidirectional(tableData.get(oldIndex).someMoreDataProperty());
                }
                int newIndex = newValue.intValue();
                if (newIndex >= 0 && newIndex < tableData.size()) {
                    if(columnIndex == 0){
                        textField.textProperty().bindBidirectional(tableData.get(newIndex).someDataProperty());
                        //System.out.println("Printing value for newIndex " + newIndex + " someData textField " + textField.getText() + " someDataProperty " + tableData.get(newIndex).someDataProperty().getValue());
                    }
                    if(columnIndex == 1){
                        textField.textProperty().bindBidirectional(tableData.get(newIndex).someMoreDataProperty());
                        //System.out.println("Printing value for newIndex " + newIndex + " someMoreData textField " + textField.getText()+ " someMoreDataProperty " + tableData.get(newIndex).someMoreDataProperty().getValue());
                    }
                    setGraphic(textField);
                } else {
                    setGraphic(null);
                }
        });
    }
}

人类:

import javafx.beans.property.SimpleStringProperty;
public class Person {
private SimpleStringProperty someData, someMoreData, additionalData;

public Person() {
    this.someData = new SimpleStringProperty("");
    this.someMoreData = new SimpleStringProperty("");
    this.additionalData = new SimpleStringProperty("");
}

public Person(String someData, String someMoreData, String additionalData) {
    this.someData = new SimpleStringProperty(someData);
    this.someMoreData = new SimpleStringProperty(someMoreData);
    this.additionalData = new SimpleStringProperty(additionalData);
}

@Override
public Object clone()throws CloneNotSupportedException{
    String someDataCloned = this.someData.getValue();
    String someMoreDataCloned = this.someMoreData.getValue();
    String additionalDataCloned = this.additionalData.getValue();
    Person personCloned = new Person(someDataCloned, someMoreDataCloned, additionalDataCloned);
    return personCloned;
}

public String getSomeData() {
    return someData.get();
}

public SimpleStringProperty someDataProperty() {
    return someData;
}

public void setSomeData(String someData) {
    this.someData.set(someData);
}

public String getSomeMoreData() {
    return someMoreData.get();
}

public SimpleStringProperty someMoreDataProperty() {
    return someMoreData;
}

public void setSomeMoreData(String someMoreData) {
    this.someMoreData.set(someMoreData);
}

public String getAdditionalData() {
    return additionalData.get();
}

public SimpleStringProperty additionalDataProperty() {
    return additionalData;
}

public void setAdditionalData(String additionalData) {
    this.additionalData.set(additionalData);
}
}

FXML:

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

<?import com.jfoenix.controls.JFXButton?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane prefHeight="400.0" prefWidth="1250.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.IndexIssueController">
<children>
    <TableView fx:id="personTableView" layoutY="50.0" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <columns>
            <TableColumn fx:id="someDataColumn" prefWidth="84.0" text="Some Data" />
            <TableColumn fx:id="someMoreDataColumn" minWidth="100.0" prefWidth="100.0" text="Some More Data" />
            <TableColumn fx:id="additionalDataColumn" minWidth="150.0" prefWidth="150.0" text="Additional Data" />
        </columns>
    </TableView>
  <JFXButton fx:id="deleteRowButton" layoutX="14.0" layoutY="363.0" onAction="#deleteRowButtonPushed" style="-fx-background-color: #0097db;" text="Delete Row" textFill="WHITE" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0">
     <font>
        <Font name="Arial" size="12.0" />
     </font>
  </JFXButton>
</children>
</AnchorPane>

1 个答案:

答案 0 :(得分:1)

您的./small_script.sh | awk -v date=$(date +%s) '{print $0 OFS date > "output_file";print}' 未得到很好的执行。在大多数情况下,不会通知索引侦听器已删除的项目。毕竟显示的项目的索引保持不变(除非那些可能变空的,如果没有足够的项目来填充所有单元格)。此外,当项目已从列表中消失时,将通知EditableTextCell的监听器。你无法通过这种方式正确解开旧项目。

由于可以写入的ObservableList s返回属性,我建议使用它们对项目进行更改。

cellValueFactory