JavaFX 2.1 TableView actualiser les éléments


J'ai ce problème commun, comme il semble l'être. Ma vue de table ne rafraîchira pas mes éléments après les avoir réinitialisés. J'ai vérifié les données et c'est le nouveau.

J'ai essayé plusieurs solutions à partir d'Internet mais sans succès.

Ne peut pas réinitialiser toutes les colonnes car il en ajoute une vide supplémentaire (je ne sais pas pourquoi) et le redimensionnement se brise.

Ma table n'est pas modifiable. Les nouvelles données sont modifiées.

Les données sont actualisées si j' modifier l'ordre des éléments et des lignes changent (:/).

Je suis juste laissé sans idées.

Pour le moment, le code d'actualisation est assez simple.

ObservableList<User> data = FXCollections.observableArrayList(User.getResellers());
reseller_table.setItems(data);

Encore une fois, les nouvelles données sont correctes. Lorsque je fais une sélection dans la vue de table, il renvoie le nouvel élément correct.

Author: kleopatra, 2012-06-16

24 answers

J'ai eu un problème similaire avec rafraîchissement. Ma solution était de limiter les opérations sur le ObservableList à celles qui fonctionnent correctement avec bind().

Supposons que ObservableList obsList est la liste sous-jacente pour le TableView.

Alors
obsList.clear() (hérité de java.util.List<>) sera pas de mise à jour le TableView correctement mais.

Appeler également setItem(obsList) n'a pas fonctionné pour déclencher une actualisation...mais...

obsList.removeAll(obsList) (remplacé par ObservableList) fonctionne très bien, car il se déclenche le changeEvent correctement.

Remplir une liste avec un contenu complètement nouveau fonctionne alors comme suit:

  • obsList.removeAll(obsList);
  • obsList.add(...); //e.g. in a loop...

Ou

  • obsList.removeAll(obsList);
  • FXCollections.copy(obsList, someSourceList)

Meilleures salutations Ingo

 33
Author: Ingo, 2018-06-04 10:59:07

Solution de contournement:

 tableView.getColumns().get(0).setVisible(false);
 tableView.getColumns().get(0).setVisible(true);
 58
Author: Daniel De León, 2012-09-27 03:45:16

Depuis JavaFX 8u60 vous pouvez utiliser(en supposant que tableView est une instance de TableView classe):

tableView.refresh();

D'après la documentation:

L'appel de refresh () force le contrôle TableView à recréer et repeupler les cellules nécessaires pour remplir les limites visuelles de la contrôle. En d'autres termes, cela force la TableView à mettre à jour ce qu'elle est de montrer à l'utilisateur. Ceci est utile dans les cas où le sous-jacent source de données a changé d'une manière qui n'est pas observée par l' TableView lui-même.

 31
Author: Elltz, 2016-09-24 00:46:50

MISE À JOUR:
Enfin, l'actualisation de tableview est résolue dans JavaFX 8u60 , qui est disponible pour un accès anticipé.


À propos de l'actualisation voir la Mise à jour des lignes dans Tableview.
Et à propos de la colonne vide voir le JavaFx 2 créer TableView avec une seule colonne. Fondamentalement, ce n'est pas une colonne, c'est-à-dire que vous ne pouvez pas sélectionner l'élément en cliquant sur ces éléments de colonne vides. C'est juste une zone vide de style comme une ligne.


MISE À JOUR: Si vous mettez à jour la tableView via reseller_table.setItems(data) alors vous n'avez pas besoin d'utiliser SimpleStringProperty. Il serait utile si vous mettiez à jour une ligne/élément uniquement. Voici un exemple complet de rafraîchissement des données de la table:

import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Dddeb extends Application {

    public static class Product {
        private String name;
        private String code;

        public Product(String name, String code) {
            this.name = name;
            this.code = code;
        }

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    private TableView<Product> productTable = new TableView<Product>();

    @Override
    public void start(Stage stage) {

        Button refreshBtn = new Button("Refresh table");
        refreshBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent arg0) {
                // You can get the new data from DB
                List<Product> newProducts = new ArrayList<Product>();
                newProducts.add(new Product("new product A", "1201"));
                newProducts.add(new Product("new product B", "1202"));
                newProducts.add(new Product("new product C", "1203"));
                newProducts.add(new Product("new product D", "1244"));

                productTable.getItems().clear();
                productTable.getItems().addAll(newProducts);
                //productTable.setItems(FXCollections.observableArrayList(newProducts));
            }
        });

        TableColumn nameCol = new TableColumn("Name");
        nameCol.setMinWidth(100);
        nameCol.setCellValueFactory(new PropertyValueFactory<Product, String>("name"));

        TableColumn codeCol = new TableColumn("Code");
        codeCol.setCellValueFactory(new PropertyValueFactory<Product, String>("code"));

        productTable.getColumns().addAll(nameCol, codeCol);
        productTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

        // You can get the data from DB
        List<Product> products = new ArrayList<Product>();
        products.add(new Product("product A", "0001"));
        products.add(new Product("product B", "0002"));
        products.add(new Product("product C", "0003"));

        //productTable.getItems().addAll(products);
        productTable.setItems(FXCollections.observableArrayList(products));

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.getChildren().addAll(productTable, refreshBtn);

        Scene scene = new Scene(new Group());
        ((Group) scene.getRoot()).getChildren().addAll(vbox);
        stage.setScene(scene);
        stage.setWidth(300);
        stage.setHeight(500);
        stage.show();
    }

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

Notez que

productTable.setItems(FXCollections.observableArrayList(newProducts));

Et

productTable.getItems().clear();
productTable.getItems().addAll(newProducts);

Sont presque équivalents. J'ai donc utilisé celui pour remplir le tableau pour la première fois et l'autre lorsque le tableau est actualisé. C'est à des fins de démonstration seulement. J'ai testé le code dans JavaFX 2.1. Et enfin, vous pouvez (et devriez) modifier votre la question de l'améliorer en déplaçant les morceaux de code dans votre réponse à votre question.

 7
Author: Uluk Biy, 2017-05-23 11:47:07

J'ai finalement trouvé une solution de contournement laide pour actualiser toutes les lignes.

void refreshTable() {
    final List<Item> items = tableView.getItems();
    if( items == null || items.size() == 0) return;

    final Item item = tableView.getItems().get(0);
    items.remove(0);
    Platform.runLater(new Runnable(){
        @Override
        public void run() {
            items.add(0, item);
        }
    });
 }
 6
Author: Javarian, 2012-07-24 05:51:55

Il semble y avoir plusieurs problèmes distincts autour d'oldItems.equals (newItems)

La première partie de RT-22463: tableView ne se mettra pas à jour même en appelant des éléments.effacer ()

// refresh table 
table.getItems().clear();
table.setItems(listEqualToOld);    

C'est corrigé. Effacer les anciens éléments avant de définir une nouvelle liste efface tous les anciens états, actualisant ainsi la table. Tout exemple où cela ne fonctionne pas peut être une régression.

Ce qui ne fonctionne toujours pas, c'est de redéfinir les éléments sans les effacer au préalable

// refresh table
table.setItems(listEqualToOld); 

C'est un problème si le tableau montre les propriétés qui ne sont pas impliquées dans la décision d'égalité d'un élément (voir l'exemple dans RT-22463 ouAubin ) et couvertes-espérons-le - par RT-39094

MISE À JOUR: RT-39094 ce dernier est également fixé, pour 8u40! Devrait bouillonner dans l'ea dans quelques semaines, spéculant sur u12 ou tel.

La raison technique semble être une vérification de l'égalité dans l'implémentation de la cellule: vérification des modifications de l'élément avant réellement l'appel de updateItem (T, boolean) a été introduit pour résoudre les problèmes de performances. Raisonnable, juste pour coder en dur" changer " = = ancien.equals(nouveau) pose des problèmes dans certains contextes.

Une solution de contournement qui me convient (pas de test formel!) est un TableRow personnalisé qui saute si une vérification d'identité est requise:

/**
 * Extended TableRow that updates its item if equal but not same.
 * Needs custom skin to update cells on invalidation of the 
 * item property.<p>
 * 
 * Looks ugly, as we have to let super doing its job and then
 * re-check the state. No way to hook anywhere else into super 
 * because all is private. <p>
 * 
 * Super might support a configuration option to check against
 * identity vs. against equality.<p>
 * 
 * Note that this is _not_ formally tested! Any execution paths calling
 * <code>updateItem(int)</code> other than through 
 * <code>indexedCell.updateIndex(int)</code> are not handled.
 * 
 * @author Jeanette Winzenburg, Berlin
 */
public class IdentityCheckingTableRow<T>  extends TableRow<T> {

    @Override
    public void updateIndex(int i) {
        int oldIndex = getIndex();
        T oldItem = getItem();
        boolean wasEmpty = isEmpty();
        super.updateIndex(i);
        updateItemIfNeeded(oldIndex, oldItem, wasEmpty);

    }

    /**
     * Here we try to guess whether super updateIndex didn't update the item if
     * it is equal to the old.
     * 
     * Strictly speaking, an implementation detail.
     * 
     * @param oldIndex cell's index before update
     * @param oldItem cell's item before update
     * @param wasEmpty cell's empty before update
     */
    protected void updateItemIfNeeded(int oldIndex, T oldItem, boolean wasEmpty) {
        // weed out the obvious
        if (oldIndex != getIndex()) return;
        if (oldItem == null || getItem() == null) return;
        if (wasEmpty != isEmpty()) return;
        // here both old and new != null, check whether the item had changed
        if (oldItem != getItem()) return;
        // unchanged, check if it should have been changed
        T listItem = getTableView().getItems().get(getIndex());
        // update if not same
        if (oldItem != listItem) {
            // doesn't help much because itemProperty doesn't fire
            // so we need the help of the skin: it must listen
            // to invalidation and force an update if 
            // its super wouldn't get a changeEvent
            updateItem(listItem, isEmpty());
        }
    }


    @Override
    protected Skin<?> createDefaultSkin() {
        return new TableRowSkinX<>(this);
    }


    public static class TableRowSkinX<T> extends TableRowSkin<T> {

        private WeakReference<T> oldItemRef;
        private InvalidationListener itemInvalidationListener;
        private WeakInvalidationListener weakItemInvalidationListener;
        /**
         * @param tableRow
         */
        public TableRowSkinX(TableRow<T> tableRow) {
            super(tableRow);
            oldItemRef = new WeakReference<>(tableRow.getItem());
            itemInvalidationListener = o -> {
                T newItem = ((ObservableValue<T>) o).getValue();
                T oldItem = oldItemRef != null ? oldItemRef.get() : null;
                oldItemRef = new WeakReference<>(newItem);
                if (oldItem != null && newItem != null && oldItem.equals(newItem)) {
                    forceCellUpdate();
                }
            };
            weakItemInvalidationListener = new WeakInvalidationListener(itemInvalidationListener);
            tableRow.itemProperty().addListener(weakItemInvalidationListener);
        }

        /**
         * Try to force cell update for equal (but not same) items.
         * C&P'ed code from TableRowSkinBase.
         */
        private void forceCellUpdate() {
            updateCells = true;
            getSkinnable().requestLayout();

            // update the index of all children cells (RT-29849).
            // Note that we do this after the TableRow item has been updated,
            // rather than when the TableRow index has changed (as this will be
            // before the row has updated its item). This will result in the
            // issue highlighted in RT-33602, where the table cell had the correct
            // item whilst the row had the old item.
            final int newIndex = getSkinnable().getIndex();
            for (int i = 0, max = cells.size(); i < max; i++) {
                cells.get(i).updateIndex(newIndex);
            }
       }

    }

    @SuppressWarnings("unused")
    private static final Logger LOG = Logger
            .getLogger(IdentityCheckingListCell.class.getName());

}

 // usage
 table.setRowFactory(p -> new IdentityCheckingTableRow());

Notez que TableCell a une vérification d'égalité codée en dur similaire, donc si la ligne personnalisée ne suffit pas, il peut être nécessaire d'utiliser une TableCell personnalisée avec une solution de contournement similaire (n'a pas exécutez un exemple où cela est nécessaire, cependant)

 2
Author: kleopatra, 2014-10-24 11:59:41

Je suppose que ce thread a une très bonne description du problème avec l'actualisation de la table.

 2
Author: Alex, 2015-03-13 01:31:56

Quel BUG ! Voici une autre solution de contournement...

public void forceRefresh() {
  final TableColumn< Prospect, ? > firstColumn = view.getColumns().get( 0 );
  firstColumn.setVisible( false );
  new Timer().schedule( new TimerTask() { @Override public void run() {
     Platform.runLater( new Runnable() { @Override public void run() {
        firstColumn.setVisible( true  ); }});
     }}, 100 );
}

J'ai fait un SSCCEpour montrer le bogue. J'encourage tout le monde à le réparer d'une autre manière plus élégante car ma solution de contournement est très laide!

 1
Author: Aubin, 2013-07-27 10:08:16

J'ai un cas d'utilisation où rien d'autre n'a aidé comme solution d'Aubin. J'ai adapté la méthode et l'ai modifiée en supprimant et en ajoutant un élément à la liste des éléments des tables car cela ne fonctionne finalement que de manière fiable avec ce hack, la bascule visible de la colonne n'a fait le travail que la première fois.

Je l'ai également signalé dans la tâche Jira: https://javafx-jira.kenai.com/browse/RT-22463

 public <T> void tableItemsRefresh(final ObservableList<T> items) {

      if (items == null || items.size() == 0)
         return;

      int idx = items.size() -1;
      final T item = items.get(idx);
      items.remove(idx);

      new Timer().schedule(new TimerTask() {
         @Override
         public void run() {
            Platform.runLater(new Runnable() {
               @Override
               public void run() {
                  items.add(item);
               }
            });
         }
      }, 100);
   } 
 1
Author: Andreas Niemeyer, 2013-08-23 09:23:51

J'ai eu le même problème et après quelques recherches c'est ma solution de contournement. J'ai trouvé que si les colonnes sont supprimées puis ré-ajoutées, la table est mise à jour.

public static <T,U> void refreshTableView(final TableView<T> tableView, final List<TableColumn<T,U>> columns, final List<T> rows) {

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

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


Exemple d'utilisation:

refreshTableView(myTableView, Arrays.asList(col1, col2, col3), rows);
 1
Author: ceklock, 2014-03-30 00:01:23

La solution par user1236048 est correcte, mais le point clé n'est pas appelé. Dans vos classes POJO utilisées pour la liste observable de la table, vous devez non seulement définir des méthodes getter et setter, mais une nouvelle appelée Property. Dans le tutoriel tableview d'Oracle (http://docs.oracle.com/javafx/2/ui_controls/table-view.htm), ils ont laissé cette partie clé hors tension!

Voici à quoi devrait ressembler la classe Person:

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 SimpleStringProperty firstNameProperty(){
        return firstName;
    }

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

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

    public SimpleStringProperty lastNameProperty(){
        return lastName;
    }

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

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

    public SimpleStringProperty emailProperty(){
            return email;
        }

}

 1
Author: Kevin Reynolds, 2014-06-12 22:24:46

Au lieu d'actualiser manuellement, vous devez utiliser des propriétés observables. Les réponses à cette question exemples le but: SimpleStringProperty et SimpleIntegerProperty TableView JavaFX

 1
Author: Andreas, 2017-05-23 11:54:37

D'après la réponse de Daniel De León

public static void refresh_table(TableView table)
{
        for (int i = 0; i < table.getColumns().size(); i++) {
    ((TableColumn)(table.getColumns().get(i))).setVisible(false);
    ((TableColumn)(table.getColumns().get(i))).setVisible(true);
    }
}
 1
Author: Phloo, 2014-07-15 20:51:58

Jetez un oeil à ce problème dans Jira: https://bugs.openjdk.java.net/browse/JDK-8098085

Un commentaire 2012-09-20 08:50 a donné une solution de contournement qui fonctionne.

//wierd JavaFX bug
reseller_table.setItems(null); 
reseller_table.layout(); 

ObservableList<User> data = FXCollections.observableArrayList(User.getResellers());
reseller_table.setItems(data);
 1
Author: Andrei Krasutski, 2016-04-04 14:46:05

JavaFX8

J'ajoute un nouvel élément par une boîte de dialogue. Voici mon code.

ObservableList<Area> area = FXCollections.observableArrayList();

À initialiser() ou setApp()

this.areaTable.setItems(getAreaData());

GetAreaData()

private ObservableList<Area> getAreaData() {
    try {
        area = AreaDAO.searchEmployees(); // To inform ObservableList
        return area;
    } catch (ClassNotFoundException | SQLException e) {
        System.out.println("Error: " + e);
        return null;
    }
}

Ajouter par boîte de dialogue.

@FXML
private void handleNewArea() {
    Area tempArea = new Area();
    boolean okClicked = showAreaDialog(tempArea);
    if (okClicked) {
        addNewArea(tempArea);
        this.area.add(tempArea); // To inform ObservableList
    }

}

Area est un POJO JavaFX ordinaire. Espérons que cela aide quelqu'un.

 1
Author: Sudhakar Krishnan, 2017-03-02 13:10:05

Méthode Initialize ()

fullNameColumn = new TableColumn("Full name");
fullNameColumn.setCellValueFactory(new PropertyValueFactory<User, String>("fullName"));
usernameColumn = new TableColumn("Username");
usernameColumn.setCellValueFactory(new PropertyValueFactory<User, String>("test"));
emailColumn = new TableColumn("Email");
emailColumn.setCellValueFactory(new PropertyValueFactory<User, String>("email"));
reseller_table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
reseller_table.getColumns().addAll(usernameColumn, fullNameColumn, emailColumn);

ObservableList<User> data = FXCollections.observableArrayList(User.getResellers());
reseller_table.setItems(data);

Classe utilisateur (Classe Hibernate POJO)

private SimpleStringProperty test;

public void setFullName(String fullName) {
  this.fullName = fullName;
  this.test = new SimpleStringProperty(fullName);    
}

public SimpleStringProperty testProperty() {
  return test;
}

Méthode Refresh ()

ObservableList<User> data = FXCollections.observableArrayList(User.getResellers());
reseller_table.setItems(data);
 0
Author: alex.dominte, 2012-06-17 12:38:41

Ma solution est similaire à la solution de contournement de Daniel De León, mais cela fonctionne également lorsque vous devez masquer la première colonne (index 0 dans son exemple). Bien sûr, vous pouvez simplement changer l'index dans sa solution, mais si vous réarrangez les colonnes, ma solution pourrait mieux fonctionner pour vous. L'idée est de masquer et de montrer la colonne par son nom au lieu de la cacher et de la montrer par son index:

private void updateMyTableView() {
    // update table view WORKAROUND !!!
    if (myTableView != null) {
        ObservableList<TableColumn<Entry, ?>> columns = myTableView.getColumns();
        for (TableColumn<Entry, ?> column : columns) {
            // at this point, we look for the specific column, which should
            // always be visible
            // therefore we use the "Column Title" String, e.g. "First name"
            if (column.getText().equals("Column Title")) {
                column.setVisible(false);
                column.setVisible(true);
            }
        }
    }
}

Il est préférable de mettre à jour votre table dans le thread de mise à jour de l'interface utilisateur. Cependant, cela fonctionne également en appelant simplement updateMyTableView(); après avoir changé quelque chose dans votre table, car JavaFX semble se mettre à jour dans le thread de l'interface utilisateur de toute façon (pas sûr à ce sujet).

Platform.runLater(new Runnable() {
    public void run() {
         updateMyTableView();
    }
});
 0
Author: Michael, 2017-05-23 12:26:04

Je ne sais pas si cela s'applique à votre situation, mais je vais poster ce qui a fonctionné pour moi.

Je change ma vue de table en fonction des requêtes / recherches en une base de données. Par exemple, une table de base de données contient des données de patients. Ma vue de table initiale dans mon programme contient tous les patients. Je peux ensuite rechercher une requête pour les patients par prénom et nom. J'utilise les résultats de cette requête pour repeupler ma liste observable. Ensuite, je réinitialise les éléments de la tableview en appelant tableview.setItems(liste d'observation):

/**
 * Searches the table for an existing Patient.
 */
@FXML
public void handleSearch() {
    String fname = this.fNameSearch.getText();
    String lname = this.lNameSearch.getText();
    LocalDate bdate = this.bDateSearch.getValue();

    if (this.nameAndDOBSearch(fname, lname, bdate)) {
        this.patientData = this.controller.processNursePatientSearch(fname, lname, bdate);
    } else if (this.birthDateSearch(fname, lname, bdate)) {
        this.patientData = this.controller.processNursePatientSearch(bdate);
    } else if (this.nameSearch(fname, lname, bdate)) {
        this.patientData = this.controller.processNursePatientSearch(fname, lname);
    }

    this.patientTable.setItems(this.patientData);
}

Les blocs if mettent à jour la liste ObservableList avec les résultats de la requête.

 0
Author: user2951579, 2014-11-30 18:06:42

Même problème ici, j'ai essayé quelques solutions et la meilleure pour moi est la suivante:

Dans initialize-method of controller, créez une observableList vide et définissez-la sur la table:

    obsBericht = FXCollections.observableList(new ArrayList<Bericht>(0));
    tblBericht.setItems(obsBericht);

Dans votre méthode de mise à jour, utilisez simplement la liste observableList, effacez-la et ajoutez les données actualisées:

        obsBericht.clear();
        obsBericht.addAll(FXCollections.observableList(DatabaseHelper.getBerichte()));
//      tblBericht.setItems(obsBericht);

, Il n'est pas nécessaire de définir les éléments de la table

 0
Author: Tom, 2015-02-26 12:36:41

Suite à la réponse de Daniel De León ...

  • j'ai introduit une propriété factice "modelChangedProperty" dans mon modèle et
  • créé une méthode refresh() dans mon modèle qui modifie la valeur de cette propriété.
  • Dans mon contrôleur, j'ai ajouté un écouteur à la propriété dummy qui met à jour la vue de la table.

-

/**
 * Adds a listener to the modelChangedProperty to update the table view
 */
private void createUpdateWorkAroundListener() {

    model.modelChangedProperty.addListener(
            (ObservableValue<? extends Boolean> arg0, final Boolean oldValue, final Boolean newValue) -> updateTableView()
            );
}

/**
 * Work around to update table view
 */
private void updateTableView() {
    TableColumn<?, ?> firstColumn = scenarioTable.getColumns().get(0);
    firstColumn.setVisible(false);
    firstColumn.setVisible(true);
}
 0
Author: Stefan, 2015-04-09 11:40:19

Je sais que cette question a 4 ans mais j'ai le même problème, j'ai essayé les solutions d'en haut et n'a pas fonctionné. J'ai également appelé méthode refresh() mais toujours pas mon résultat attendu. Je poste donc ici ma solution peut-être aider quelqu'un.

Question db = center.getSelectionModel().getSelectedItem();
new QuestionCrud().deleteQ(db.getId());
ObservableList<Question> aftDelete = FXCollections.observableArrayList(
        (new QuestionCrud()).all()
        );
center.setItems(aftDelete);

Même avant cela, j'ai utilisé une autre variable dans ObeservableList pour définir des éléments dans la tableview, j'appelle cela une "méthode sale" mais jusqu'à ce que j'obtienne une meilleure solution, c'est ok.

 0
Author: Wolf Marian, 2016-12-30 19:38:48

J'ai essayé de trouver un moyen d'actualiser la tableView(ScalaFx) pendant 3-4 heures. J'ai enfin obtenu une réponse. Je veux juste publier ma solution car j'ai déjà perdu des heures.

-Pour récupérer les lignes de la base de données, j'avais l'habitude de déclarer une méthode qui renvoie ObservableBuffer.

Ma CLASSE JDBC

    //To get all customer details
def getCustomerDetails : ObservableBuffer[Customer] = {

val customerDetails = new ObservableBuffer[Customer]()
  try {

    val resultSet = statement.executeQuery("SELECT * FROM MusteriBilgileri")

    while (resultSet.next()) {

      val musteriId = resultSet.getString("MusteriId")
      val musteriIsmi = resultSet.getString("MusteriIsmi")
      val urununTakildigiTarih = resultSet.getDate("UrununTakildigiTarih").toString
      val bakimTarihi = resultSet.getDate("BakimTarihi").toString
      val urununIsmi = resultSet.getString("UrununIsmi")
      val telNo = resultSet.getString("TelNo")
      val aciklama = resultSet.getString("Aciklama")

      customerDetails += new Customer(musteriId,musteriIsmi,urununTakildigiTarih,bakimTarihi,urununIsmi,telNo,aciklama)

    }
  } catch {
    case e => e.printStackTrace
  }

  customerDetails
}

-Et j'ai créé un objet TableView.

var table = new TableView[Customer](model.getCustomerDetails)
table.columns += (customerIdColumn,customerNameColumn,productInstallColumn,serviceDateColumn,
        productNameColumn,phoneNoColumn,detailColumn)

-Et finalement j'ai eu la solution. Dans le bouton actualiser, j'ai inséré ce code;

table.setItems(FXCollections.observableArrayList(model.getCustomerDetails.delegate))

Modèle est la référence de ma classe de connexion jdbc

val model = new ScalaJdbcConnectSelect

Ce sont les codes scalafx mais cela donne une idée de javafx

 0
Author: Muhammed Yalçın Kuru, 2017-02-21 15:45:47

Bien après avoir cherché toutes les solutions possibles. J'ai essayé d'abord d'effacer les données, puis ajouté dans tableview tableView.getItems().clear(); cela n'a toujours pas résolu mon problème. J'ai essayé toutes les réponses données ici mais cela n'a pas fonctionné pour moi et j'avais toujours des objets périmés dans mon tableau comme indiqué dans l'image ci-dessous:

entrez la description de l'image ici

Afin de le réparer, j'ai créé une étiquette FACTICE et utilisé setGraphic comme suit:

entrez la description de l'image ici

 0
Author: Vishrant, 2018-04-26 21:28:59

我始終認為利用更改TableColumn的visable屬性的方法違反databinding的精神,若這是JavaFX的bug那也早就該接決了,不應該拖到Java8了還不解決。

{[3] }trtrace javafx的source code , ,有有bbug。利用listener有有。 。 也嘗試利用jface中的propertychangesupport方式宣告pojo有有。 。 最後將DoublepropertyWrWritableobjectvalue,。 。
                                                           解決於台灣台北

J'avais raffermi la propriété visible de la colonne de changement d'utilisation n'est pas conforme au but de l'automatisation de la liaison de données.

Après avoir tracé le code source de JavaFX TableView. Je n'ai jamais découvert de code de problème pour la liaison Tableview question. Après 4 semaines, j'ai changé le type du champ POJO de DoubleProperty à WritableObjectValue, le problème a été résolu.

                                               resolve in Taiwan Taipei.

Exemple de code:

public class CostAnalytics{
protected WritableObjectValue<Double> subtotal=new SimpleObjectProperty<Double>();//利用WritableObjectValue達到自動更新目的,不需要使用個別Column操作setVisable(false)及setVisable(true)
//...
public void setQuantity(double quantity) {
    this.pcs.firePropertyChange("quantity", this.quantity, quantity);
    this.quantity.set(quantity);
    this.calsSubtotal();
}
public WritableObjectValue<Double> getSubtotal() {//利用WritableObjectValue達到自動更新目的,不需要使用個別Column操作setVisable(false)及setVisable(true)
    return subtotal;
}
///...
}


TableColumn<CostAnalytics, Double> subtotal = new TableColumn<CostAnalytics, Double>(
            "小計");
subtotal.setCellValueFactory(new Callback<CellDataFeatures<CostAnalytics, Double>, ObservableValue<Double>>() {

        public ObservableValue<Double> call(
                CellDataFeatures<CostAnalytics, Double> p) {
            WritableObjectValue<Double> result = p.getValue().getSubtotal();// //利用WritableObjectValue達到自動更新目的,不需要使用個別Column操作setVisable(false)及setVisable(true)
            // return (ObservableValue<Double>)
            // result;//利用WritableObjectValue達到自動更新目的,不需要使用個別Column操作setVisable(false)及setVisable(true)
            // return new
            // ReadOnlyObjectWrapper<Double>(p.getValue().getSubtotal());//造成無法自動更新
            return (ObservableValue<Double>) p.getValue().getSubtotal();// 利用WritableObjectValue達到自動更新目的,不需要使用個別Column操作setVisable(false)及setVisable(true)
        }

    });
 -10
Author: 楊竣壹, 2015-05-31 08:35:21