JavaFX 2.1 rafraîchissements TableView
j'ai cette question commune, telle qu'elle semble l'être. Ma vue de table ne rafraîchira pas mes articles après que je les ai réinitialisés. J'ai vérifié les données et c'est le nouveau.
j'ai essayé plusieurs solutions sur internet mais sans succès.
ne peut pas réinitialiser toutes les colonnes parce qu'il ajoute un vide un supplémentaire (ne sait pas pourquoi) et la redimensionnement se brise juste.
ma table n'est pas modifiable . Nouvelle les données sont modifiées.
les données sont rafraîchies si I change l'ordre des articles et les lignes changent (:|).
Je n'ai plus d'idées.
pour le moment le code de rafraîchissement est assez simple.
ObservableList<User> data = FXCollections.observableArrayList(User.getResellers());
reseller_table.setItems(data);
Encore une fois les nouvelles données sont correctes. Quand je fais une sélection à la tableView il retourne le nouvel article correct.
24 réponses
j'ai eu un problème similaire avec rafraîchissant. Ma solution était de limiter les opérations sur le ObservableList
à celles qui fonctionnent correctement avec bind()
.
suppose ObservableList obsList
est la liste sous-jacente pour le TableView
.
puis
obsList.clear()
(hérité de java.util.List<>
) sera pas mettre à jour le TableView
correctement mais.
Aussi appelé setItem(obsList)
a pas de travail pour déclencher une actualisation...mais...
obsList.removeAll(obsList)
(remplacé par ObservableList
) fonctionne très bien parce qu'il déclenche le changement correctement.
remplir une liste avec un contenu entièrement nouveau fonctionne alors comme suit:
-
obsList.removeAll(obsList);
-
obsList.add(...); //e.g. in a loop...
ou
-
obsList.removeAll(obsList);
-
FXCollections.copy(obsList, someSourceList)
en ce qui concerne Meilleur Ingo
solution de contournement:
tableView.getColumns().get(0).setVisible(false);
tableView.getColumns().get(0).setVisible(true);
depuis JavaFX 8u60
vous pouvez utiliser(en supposant que tableView
est une instance de TableView classe):
tableView.refresh();
de la documentation:
appelant refresh () force le contrôle de TableView à recréer et repeupler les cellules nécessaires pour remplir le visuel limites de la contrôle. En d'autres termes, cela force TableView à mettre à jour est de montrer à l'utilisateur. Ceci est utile dans les cas d'où le sous-jacent source de données a changé d'une manière qui n'est pas observé par le TableView m'.
mise à jour:
Enfin tableview rafraîchissant est résolu dans JavaFX 8u60 , qui est disponible pour un accès précoce.
à propos de rafraîchissement voir les lignes de mise à jour dans Tableview .
Et à propos de la colonne vide voir le JavaFx 2 Créer TableView avec la colonne simple . Fondamentalement, il n'est pas une colonne, c'est-à-dire que vous ne pouvez pas sélectionner l'élément en cliquant sur les éléments de cette colonne vide. Il s'agit simplement d'une zone vierge coiffée comme une rangée.
mise à jour: si vous mettez à jour tableView via reseller_table.setItems(data)
alors vous n'avez pas besoin d'utiliser SimpleStringProperty
. Il serait utile que vous ne mettiez à jour qu'une ligne/item. Voici un exemple de travail 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);
}
}
noter que
productTable.setItems(FXCollections.observableArrayList(newProducts));
et
productTable.getItems().clear();
productTable.getItems().addAll(newProducts);
sont presque équivalents. J'ai donc utilisé l'un pour remplir la table pour la première fois et d'autres lorsque le tableau est actualisé. C'est uniquement à des fins de démonstration. J'ai testé le code dans JavaFX 2.1. Et enfin, vous pouvez (et devriez) éditer votre question pour l'améliorer en déplaçant les morceaux de code dans votre réponse à votre question.
j'ai enfin trouvé une mauvaise solution pour rafraîchir 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);
}
});
}
il semble y avoir plusieurs problèmes distincts autour de oldItems.equals (newItems)
la première partie de RT-22463 : tableView ne mettra pas à jour même si vous appelez des items.clear ()
// refresh table
table.getItems().clear();
table.setItems(listEqualToOld);
c'est réglé. Effacer les anciens éléments avant de définir une nouvelle liste efface tout l'état ancien, rafraîchissant ainsi la table. Tout exemple où cela ne fonctionne pas pourrait être une régression.
ce qui ne fonctionne toujours pas est modifier les éléments sans les effacer d'abord
// refresh table
table.setItems(listEqualToOld);
C'est un problème si la table montre des propriétés qui ne sont pas impliqués dans la décision d'égalité d'un article (voir l'exemple dans RT-22463 ou D'Aubin ) et couvert - avec un peu de chance - par RT-39094
mise à jour : RT-39094 ce dernier est également fixé, pour 8u40! Devrait remonter dans l'ae dans quelques semaines, spéculant sur u12 ou autre.
la raison technique semble être un contrôle d'égalité dans la mise en œuvre de cell: vérifier les changements de l'élément avant d'appeler effectivement updateItem(T, booléen) a été introduit pour corriger les problèmes de performance. Raisonnable, juste à coder en dur "modifier" == vieux.equals(nouveau) pose des problèmes dans certains contextes.
Une façon de contourner ce qui est bien pour moi (pas de tests formels!) est une TableRow personnalisée qui saute dans le cas où un contrôle d'identité est requis:
/**
* 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 un contrôle d'égalité codé en dur similaire, donc si la ligne personnalisée ne suffit pas, il pourrait être nécessaire d'utiliser une TableCell personnalisée avec une solution similaire (n'ont pas couru dans un exemple où c'est nécessaire, bien que)
quel BUG ! Voici un autre 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 SSCCE à afficher le bug . J'encourage tout le monde à le réparer d'une autre manière plus élégante parce que mon contournement est très laid!
J'ai un cas d'utilisation où rien d'autre n'a aidé que la solution D'Aubin. J'ai adapté la méthode et l'ai modifié en supprimant et en ajoutant un élément à la liste des éléments des tables car il fonctionne à la fin seulement fiable avec ce hack, la colonne Visible toggle a fait le travail que la première fois.
Je l'ai signalé aussi 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);
}
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 enlevées et 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);
la solution par user1236048 est correcte, mais le point clé n'est pas appelé. Dans vos classes de POJO utilisées pour la liste observable de la table, vous n'avez pas seulement à définir les méthodes getter et setter, mais une nouvelle méthode appelée propriété. Dans le tutoriel tableview D'Oracle ( http://docs.oracle.com/javafx/2/ui_controls/table-view.htm ), ils ont laissé cette pièce clé ouverte!
voici à quoi devrait ressembler la classe Personne:
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;
}
}
au lieu de rafraîchir manuellement, vous devriez utiliser des propriétés observables. Les réponses à cette question illustrent le but: SimpleStringProperty and Simpleintegeproperty table JavaFX
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);
}
}
regardez ce numéro dans Jira: https://bugs.openjdk.java.net/browse/JDK-8098085
un commentaire 2012-09-20 08:50 a donné une solution qui fonctionne.
//wierd JavaFX bug
reseller_table.setItems(null);
reseller_table.layout();
ObservableList<User> data = FXCollections.observableArrayList(User.getResellers());
reseller_table.setItems(data);
JavaFX8
j'ajoute un nouvel article par 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.
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);
Utilisateur de la Classe (Hibernate Classe 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);
ma solution est similaire à la solution de contournement de Daniel de León , mais elle fonctionne aussi quand vous avez besoin de cacher 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éorganisez les colonnes, ma solution pourrait mieux fonctionner pour vous. L'idée est de cacher 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 aussi en appelant simplement updateMyTableView();
après que vous ayez changé quelque chose dans votre table, puisque JavaFX semble 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();
}
});
Je ne suis pas sûr que cela s'applique à votre situation, mais je vais poster ce qui a fonctionné pour moi.
je change ma vue de table basée sur les requêtes / recherches à une base de données. Par exemple, une table de base de données contient des données sur les patients. Ma vue de table initiale dans mon programme contient tous les Patients. Je peux alors rechercher la requête pour les Patients par prénom et lastName. J'ai utiliser les résultats de cette requête pour repeupler mon Observables liste. Puis j'ai réinitialisé les éléments dans tableview en appelant tableview.setItems (observableList):
/**
* 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.
Même problème ici, j'ai essayé quelques solutions et le meilleur pour moi est le suivant:
initialize-méthode de contrôleur, de créer un vide observableList et de le régler sur la table:
obsBericht = FXCollections.observableList(new ArrayList<Bericht>(0));
tblBericht.setItems(obsBericht);
dans votre mise à jour-méthode, il suffit d'utiliser la liste observableList, effacer et ajouter les données rafraîchies:
obsBericht.clear();
obsBericht.addAll(FXCollections.observableList(DatabaseHelper.getBerichte()));
// tblBericht.setItems(obsBericht);
il n'est pas nécessaire de remettre les éléments de la table
suite à la réponse de Daniel de León ...
- j'ai introduit une propriété fictive "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 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);
}
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 ça n'a pas marché. J'ai également appelé méthode refresh() mais toujours pas mon résultat attendu. Donc je poste 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 si avant cela J'ai utilisé une autre variable dans ObeservableList pour placer des articles dans la tableview, j'appelle cela une" méthode dégoûtante " mais jusqu'à ce que j'obtienne une meilleure solution est ok.
j'ai essayé de trouver un moyen de rafraîchir le tableView(ScalaFx) pendant 3-4 heures. J'ai enfin obtenu une réponse. Je veux juste publier ma solution parce que j'ai déjà perdu des heures.
- pour récupérer les lignes de la base de données, j'ai utilisé pour déclarer une méthode qui renvoie Observabuffer.
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 enfin je reçu de solution. Dans le bouton Rafraîchir, 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 il donne une idée à javafx
bien après avoir recherché toutes les solutions possibles. J'ai d'abord essayé d'Effacer les données, puis j'ai ajouté dans tableview tableView.getItems().clear();
, mais cela ne résout pas mon problème. J'ai essayé toutes les réponses données ici mais n'a pas travaillé pour moi et j'avais encore des objets périmés dans ma table comme montré dans l'image ci-dessous:
pour le fixer, j'ai créé une étiquette factice et utilisé setGraphic
comme suit:
我始終認為利用更改TableColumn的visable屬性的方法違反databinding的精神,若這是JavaFX的bug那也早就該接決了,不應該拖到Java8了還不解決。
經過trace JavaFX 的source code後,並沒有發現bug。利用Listener等方法觀察也沒有異樣。也嘗試利用JFace中的PropertyChangeSupport方式宣告pojo內容變更也沒有效果。Xdoubleproperty xdoubleabjectableabobjectvalue xdoubleabombant
解決於台灣台北
j'avais confirmé le changement D'utilisation colonne visable propriété N'est pas conforme à l'objectif d'automatisation de 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 le problème de liaison de Tableview. Après il y a 4 semaines, J'ai changé le type de POJO field 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)
}
});