JavaFX - удаление строки в табличном представлении с помощью настраиваемой текстовой ячейки таблицы - PullRequest
0 голосов
/ 18 мая 2018

Я реализую настраиваемую редактируемую текстовую ячейку, чтобы получить функцию TAB в табличном представлении.Все работает нормально, но когда я удаляю строку, редактируемые ячейки под удаленной строкой изменяют значения одновременно.Таким образом, ввод в ячейку под удаленной строкой изменит элемент для нескольких ячеек в этом столбце.

Снимок экрана 1 - выбран вид таблицы, заполненный начальными значениями и удаляемой строкой
Снимок экрана 2 - Вид таблицы после удаления выбранной строки
Снимок 3: редактируемые текстовые ячейки в строках под удаленными строками обновляются одновременнозначения редактируемой ячейки вне текущего представления получают поведение, упомянутое выше.

Ниже приведен мой код.

Main:

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 голосов
/ 18 мая 2018

Ваш EditableTextCell не реализован хорошо.В большинстве случаев слушатель индекса не будет уведомлен об удаленных элементах.Индексы отображаемых элементов остаются неизменными (за исключением тех, которые могут стать пустыми, если не хватает элементов для заполнения всех ячеек).Кроме того, слушатель ObservableList получает уведомление, когда элемент уже отсутствует в списке.Вы не можете правильно отсоединить от старого элемента таким образом.

Поскольку cellValueFactory s возвращают свойства, в которые можно записывать, я рекомендую использовать их для внесения изменений в элементы.

public class EditableTextCell<E> extends TableCell<E, String> {

    private final TextField textField;
    private boolean updating = false;

    public EditableTextCell() {
        textField = new TextField();
        textField.textProperty().addListener((o, oldValue, newValue) -> {
            if (!updating) {
                ((WritableValue<String>) getTableColumn().getCellObservableValue((E) getTableRow().getItem())).setValue(newValue);
            }
        });
    }

    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);
        if (empty) {
            setGraphic(null);
        } else {
            setGraphic(textField);
            if (!Objects.equals(textField.getText(), item)) { // prevent own updates from moving the cursor
                updating = true;
                textField.setText(item);
                updating = false;
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...