Вопрос по javafx-2 – JavaFx 2.1, 2.2 проблема обновления TableView

3

Мое приложение использует JPA для чтения данных в TableView, а затем их изменения и отображения. Таблица обновила измененную запись под JavaFx 2.0.3. В JavaFx 2.1, 2.2 таблица больше не будет обновлять обновление. Я обнаружил, что у других людей есть похожая проблема. Мой план состоял в том, чтобы продолжать использовать 2.0.3, пока кто-то не решит проблему в соответствии с 2.1 и 2.2. Теперь я знаю, что это не ошибка, и она не будет исправлена. Ну, я не знаю, как с этим справиться. Ниже приведены коды, модифицированные из примера демонстрации, чтобы показать проблему. Если я добавляю новую запись или удаляю старую запись из таблицы, таблица обновляется нормально. Если я изменю запись, таблица не обновит изменения, пока не будет выполнено действие добавления, удаления или сортировки. Если я удалю измененную запись и добавлю ее снова, таблица обновится. Но измененная запись ставится у кнопки таблицы. Что ж, если я удалю измененную запись, добавлю эту же запись и переместу запись в исходное место, таблица больше не будет обновляться. Ниже приведен полный код, пожалуйста, пролите свет на это.

    import javafx.application.Application;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.geometry.HPos;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.scene.layout.GridPane;
    import javafx.scene.layout.HBox;
    import javafx.scene.layout.VBox;
    import javafx.scene.text.Font;
    import javafx.stage.Modality;
    import javafx.stage.Stage;
    import javafx.stage.StageStyle;

    public class Main extends Application {

        private TextField firtNameField = new TextField();
        private TextField lastNameField = new TextField();
        private TextField emailField = new TextField();
        private Stage editView;
        private Person fPerson;

        public static class Person {

            private final SimpleStringProperty firstName;
            private final SimpleStringProperty lastName;
            private final SimpleStringProperty email;

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

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

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

            public String getLastName() {
                return lastName.get();
            }

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

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

            public void setEmail(String fName) {
                email.set(fName);
            }
        }
        private TableView<Person> table = new TableView<Person>();
        private final ObservableList<Person> data =
                FXCollections.observableArrayList(
                new Person("Jacob", "Smith", "[email protected]"),
                new Person("Isabella", "Johnson", "[email protected]"),
                new Person("Ethan", "Williams", "[email protected]"),
                new Person("Emma", "Jones", "[email protected]"),
                new Person("Michael", "Brown", "[email protected]"));

        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(535);
            stage.setHeight(535);
            editView = new Stage();

            final Label label = new Label("Address Book");
            label.setFont(new Font("Arial", 20));

            TableColumn firstNameCol = new TableColumn("First Name");
            firstNameCol.setCellValueFactory(
                    new PropertyValueFactory<Person, String>("firstName"));
            firstNameCol.setMinWidth(150);

            TableColumn lastNameCol = new TableColumn("Last Name");
            lastNameCol.setCellValueFactory(
                    new PropertyValueFactory<Person, String>("lastName"));
            lastNameCol.setMinWidth(150);
            TableColumn emailCol = new TableColumn("Email");
            emailCol.setMinWidth(200);
            emailCol.setCellValueFactory(
                    new PropertyValueFactory<Person, String>("email"));

            table.setItems(data);
            table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
    //--- create a edit button and a editPane to edit person   
            Button addButton = new Button("Add");
            addButton.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    fPerson = null;
                    firtNameField.setText("");
                    lastNameField.setText("");
                    emailField.setText("");
                    editView.show();
                }
            });
            Button editButton = new Button("Edit");
            editButton.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    if (table.getSelectionModel().getSelectedItem() != null) {
                        fPerson = table.getSelectionModel().getSelectedItem();
                        firtNameField.setText(fPerson.getFirstName());
                        lastNameField.setText(fPerson.getLastName());
                        emailField.setText(fPerson.getEmail());
                        editView.show();
                    }
                }
            });
            Button deleteButton = new Button("Delete");
            deleteButton.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    if (table.getSelectionModel().getSelectedItem() != null) {
                        data.remove(table.getSelectionModel().getSelectedItem());
                    }
                }
            });
            HBox addEditDeleteButtonBox = new HBox();
            addEditDeleteButtonBox.getChildren().addAll(addButton, editButton, deleteButton);
            addEditDeleteButtonBox.setAlignment(Pos.CENTER_RIGHT);
            addEditDeleteButtonBox.setSpacing(3);

            GridPane editPane = new GridPane();
            editPane.getStyleClass().add("editView");
            editPane.setPadding(new Insets(3));
            editPane.setHgap(5);
            editPane.setVgap(5);
            Label personLbl = new Label("Person:");
            editPane.add(personLbl, 0, 1);
            GridPane.setHalignment(personLbl, HPos.LEFT);

            firtNameField.setPrefWidth(250);
            lastNameField.setPrefWidth(250);
            emailField.setPrefWidth(250);
            Label firstNameLabel = new Label("First Name:");
            Label lastNameLabel = new Label("Last Name:");
            Label emailLabel = new Label("Email:");

            editPane.add(firstNameLabel, 0, 3);
            editPane.add(firtNameField, 1, 3);
            editPane.add(lastNameLabel, 0, 4);
            editPane.add(lastNameField, 1, 4);
            editPane.add(emailLabel, 0, 5);
            editPane.add(emailField, 1, 5);
            GridPane.setHalignment(firstNameLabel, HPos.RIGHT);
            GridPane.setHalignment(lastNameLabel, HPos.RIGHT);
            GridPane.setHalignment(emailLabel, HPos.RIGHT);

            Button saveButton = new Button("Save");
            saveButton.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    if (fPerson == null) {
                        fPerson = new Person(
                                firtNameField.getText(),
                                lastNameField.getText(),
                                emailField.getText());
                        data.add(fPerson);
                    } else {
                        int k = -1;
                        if (data.size() > 0) {
                            for (int i = 0; i < data.size(); i++) {
                                if (data.get(i) == fPerson) {
                                    k = i;
                                }
                            }
                        }
                        fPerson.setFirstName(firtNameField.getText());
                        fPerson.setLastName(lastNameField.getText());
                        fPerson.setEmail(emailField.getText());
                        data.set(k, fPerson);
                        table.setItems(data);

    //  The following will work, but edited person has to be added to the button
    //
    //                    data.remove(fPerson);
    //                    data.add(fPerson);

    // add and remove refresh the table, but now move edited person to original spot, 
    // it failed again with the following code
    //                    while (data.indexOf(fPerson) != k) {
    //                        int i = data.indexOf(fPerson);
    //                        Collections.swap(data, i, i - 1);
    //                    }
                    }
                    editView.close();
                }
            });
            Button cancelButton = new Button("Cancel");
            cancelButton.setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    editView.close();
                }
            });

            HBox saveCancelButtonBox = new HBox();
            saveCancelButtonBox.getChildren().addAll(saveButton, cancelButton);
            saveCancelButtonBox.setAlignment(Pos.CENTER_RIGHT);
            saveCancelButtonBox.setSpacing(3);

            VBox editBox = new VBox();
            editBox.getChildren().addAll(editPane, saveCancelButtonBox);

            Scene editScene = new Scene(editBox);
            editView.setTitle("Person");
            editView.initStyle(StageStyle.UTILITY);
            editView.initModality(Modality.APPLICATION_MODAL);
            editView.setScene(editScene);
            editView.close();

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

            ((Group) scene.getRoot()).getChildren().addAll(vbox);

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

Ваш Ответ

7   ответов
0

У меня та же проблема, и я не могу добавитьSimpleStringProperty для POJO, используемого JPA, делает это немного проблематичным. Но мне кажется, что это должно быть исправимо, потому что я заметил следующее поведение:

  1. In my application, clicking on a row in the table populates some text fields on the screen, that the user can then edit.
  2. At that point the user can save the data, or create a new item with the same or changed data. If the user creates a new item, which is then inserted into the observable list that the tableview represents, the change is immediately reflected in the contents of the tableview. However if the user just saves the change the new data is not reflected in the table. To put the new data in the list I'm simply doing

    trialList.set(currentIndex, tempTrial);
    
  3. And here's what I think points to this as a fixable issue: if I scroll the affected row out of view on the table and then scroll it back, the 'new' value(s) are now presented.

Надеюсь, это можно исправить. Извините, это не ответ, так сказать, но может дать некоторую информацию для исправления.

Кто-то из другого JIRA опубликовал решение. Чтобы обновить, выполните: tableview.getColumns (). Get (0) .setVisible (false) и следующий setVisible (true). Это прекрасно работает. Lewis Liu
0

это сработало для меня

@FXML 
private void refreshTableView()
{
  firstNameCol.setVisible(false);
  lastNameCol.setVisible(false);
  emailCol.setVisible(false); 
  firstNameCol.setVisible(true);
  lastNameCol.setVisible(true);
  emailCol.setVisible(true);
} 
1

Обновления элементов управления JavaFX на основе уведомлений обычно требуют, чтобы свойства объекта модели данных, поддерживающего ваш графический интерфейс, соответствовали минимальному определению для bean-компонента JavaFX.

Ниже приведен пример минимального кода, необходимого для того, чтобы свойство JavaFX удовлетворяло этим требованиям:

public class Client extends DB {

    private IntegerProperty id =         new SimpleIntegerProperty();
    private StringProperty  lastName =   new SimpleStringProperty();
    private StringProperty  firstName =  new SimpleStringProperty();


    public final int getID() {return this.id.get(); }
    void setID(int id) { this.id.set(id); }
    public final IntegerProperty idProperty() { return this.id; }

    public final String getLastName() { return this.lastName.get(); }
    public final void setLastName(String ln) { this.lastName.set(ln); }
    public final StringProperty lastNameProperty() { return this.lastName; }

    public final String getFirstName() { return this.firstName.get(); }
    public final void setFirstName(String fn) { this.firstName.set(fn); }
    public final StringProperty firstNameProperty() { return this,.firstName; }
    :
    :
}    

Если посмотреть на ваш код, вы не увидите, что ваши свойства удовлетворяют требованиям для JavFX Bean. Таким образом, автоматические обновления на основе уведомлений не будут выполняться.

5

Увидетьответ на Обновление строк в Tableview, Добавьте эти геттеры, и это будет просто работать.
Кроме того, так какdata являетсяObservableList который устанавливается в качестве элементов tableView, любые изменения в этомdata список будет отражен вtable.getItems() тоже. А именно не надоtable.setItems(data) снова.

JPA POJO реализует Сериализуемый. SimpleStringProperty не является сериализуемым типом. Я даже не могу добавить SimpleStringProperty в мой POJO. Lewis Liu
EстьJira issue об этой проблеме. Вы можете проголосовать за это.
Добавление геттеров делает демо работающим. Но это будет проблемой для моего приложения. Я использую Netbeans для генерации около 100 классов сущностей из базы данных. И у каждого класса есть много полей. Это будет много получателей, чтобы добавить. С другой стороны, что делает JavaFX 2.0.3 работает? Lewis Liu
5

Я нашел простой обходной путь для запуска обновления TableView вЭлементы обновления JavaFX 2.1 TableView, Это решило проблему для меня.

Добавьте это к своему коду:

tableView.getColumns().get(0).setVisible(false);
tableView.getColumns().get(0).setVisible(true);
0

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

public static <T,U> void refreshTableView(final TableView<T> tableView, final List<TableColumn<T,U>> columns, final List<T> rows) {
    if (tableView == null) {
        throw new NullPointerException();
    }
    if (columns == null) {
        throw new NullPointerException();
    }
    if (rows == null) {
        throw new NullPointerException();
    }

    tableView.getColumns().clear();
    tableView.getColumns().addAll(columns);

    ObservableList<T> list = FXCollections.observableArrayList(rows);
    tableView.setItems(list);
}


Пример использования:

refreshTableView(myTableView, Arrays.asList(col1, col2, col3), rows);
5

просматривая код TableView.java, есть приватный метод refresh (), который просто выполняет

getProperties().put(TableViewSkinBase.REFRESH, Boolean.TRUE); 

Наконец, код ниже работал для меня (Java8). (будьте осторожны, имя константы не REFRESH, а RECREATE)

tableView.getProperties().put(TableViewSkinBase.RECREATE, Boolean.TRUE);

(чтение кода javafx, это приведет к повторному созданию ячейки)

Похожие вопросы