JavaFX 2.1 TableView actualiza los elementos

Tengo este problema común, como parece ser. Mi vista de tabla no actualizará mis elementos después de que los reinicie. He comprobado los datos y es el nuevo.

Intenté una solución múltiple de internet pero no tuve éxito.

No se pueden restablecer todas las columnas porque agrega una vacía adicional (no sé por qué) y el tamaño simplemente rompe.

Mi mesa no es editable Los nuevos datos han cambiado.

Los datos se actualizan si cambio el orden de los elementos y las filas cambian (: |).

Me quedé sin ideas.

Por el momento, el código de actualización es bastante simple.

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

De nuevo, los datos nuevos son correctos. Cuando selecciono TableView, devuelve el nuevo Item correcto.

Tuve un problema similar con refrescante. Mi solución fue restringir las operaciones en la ObservableList a aquellas que funcionan correctamente con bind() .

Asum que ObservableList obsList es la lista subyacente para TableView .

Entonces
obsList.clear() (heredado de java.util.List<> ) no actualizará TableView correctamente pero.

También llamar a setItem(obsList) no funcionó para desencadenar una actualización … pero …

obsList.removeAll(obsList) (sobreescrito por ObservableList ) funciona bien porque desencadena el changeEvent correctamente.

Volver a llenar una lista con contenido completamente nuevo funciona de la siguiente manera:

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

o

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

Saludos cordiales Ingo

Solución:

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

Desde JavaFX 8u60 puede usar (suponiendo que tableView es una instancia de la clase TableView ):

 tableView.refresh(); 

De la documentación:

Llamar a refresh () fuerza al control TableView a recrear y repoblar las celdas necesarias para rellenar los límites visuales del control. En otras palabras, esto obliga a TableView a actualizar lo que muestra al usuario. Esto es útil en casos donde la fuente de datos subyacente ha cambiado de una manera que no es observada por TableView.

ACTUALIZAR:
Finalmente, la actualización de tablas se resuelve en JavaFX 8u60 , que está disponible para acceso anticipado.


Acerca de la actualización, consulte la Actualización de filas en TableView .
Y sobre la columna en blanco, vea JavaFx 2 crear TableView con una sola columna . Básicamente no es una columna, es decir, no puede seleccionar el elemento haciendo clic en estos elementos de columna en blanco. Es solo un área en blanco con el estilo de una fila.


ACTUALIZACIÓN: Si está actualizando tableView a través de reseller_table.setItems(data) entonces no necesita usar SimpleStringProperty . Sería útil si estuviera actualizando solo una fila / elemento. Aquí hay un ejemplo completo de trabajo de actualizar los datos de la tabla:

 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 productTable = new TableView(); @Override public void start(Stage stage) { Button refreshBtn = new Button("Refresh table"); refreshBtn.setOnAction(new EventHandler() { @Override public void handle(ActionEvent arg0) { // You can get the new data from DB List newProducts = new ArrayList(); 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("name")); TableColumn codeCol = new TableColumn("Code"); codeCol.setCellValueFactory(new PropertyValueFactory("code")); productTable.getColumns().addAll(nameCol, codeCol); productTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); // You can get the data from DB List products = new ArrayList(); 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); } } 

Tenga en cuenta que

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

y

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

son casi equivalentes. Así que usé el que llena la mesa por primera vez y el otro cuando la mesa se actualiza. Es solo para propósitos de demostración. He probado el código en JavaFX 2.1. Y, por último, puede (y debería) editar su pregunta para mejorarla moviendo los elementos del código en su respuesta a su pregunta.

Finalmente encontré una solución fea para actualizar todas las filas.

 void refreshTable() { final List 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); } }); } 

Parece que hay varios problemas separados alrededor de oldItems.equals (newItems)

La primera parte de RT-22463 : tableView no se actualizará incluso si llama a items.clear ()

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

eso está arreglado. Limpiar los elementos anteriores antes de establecer una nueva lista borra todo el estado anterior, refrescando así la tabla. Cualquier ejemplo en el que esto no funcione podría ser una regresión.

Lo que aún no funciona es volver a establecer los elementos sin borrar primero

 // refresh table table.setItems(listEqualToOld); 

Eso es un problema si la tabla muestra propiedades que no están involucradas en la decisión igual de un artículo (ver ejemplo en RT-22463 o Aubin ) y está cubierto – con suerte – por RT-39094

ACTUALIZACIÓN : RT-39094 este último también está arreglado, ¡para 8u40! Debería burbujear dentro de la ea en un par de semanas, especulando sobre u12 o tal.

La razón técnica parece ser una comprobación de igualdad en la implementación de la célula: se introdujo la comprobación de cambios del elemento antes de llamar realmente a updateItem (T, boolean) para corregir problemas de rendimiento. Razonable, solo para codificar “cambio” == old.equals (nuevo) plantea problemas en algunos contextos.

Una solución alternativa que está bien para mí (¡sin pruebas formales!) Es un TableRow personalizado que salta si se requiere verificación de identidad:

 /** * Extended TableRow that updates its item if equal but not same. * Needs custom skin to update cells on invalidation of the * item property.

* * 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.

* * Super might support a configuration option to check against * identity vs. against equality.

* * Note that this is _not_ formally tested! Any execution paths calling * updateItem(int) other than through * indexedCell.updateIndex(int) are not handled. * * @author Jeanette Winzenburg, Berlin */ public class IdentityCheckingTableRow extends TableRow { @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 extends TableRowSkin { private WeakReference oldItemRef; private InvalidationListener itemInvalidationListener; private WeakInvalidationListener weakItemInvalidationListener; /** * @param tableRow */ public TableRowSkinX(TableRow tableRow) { super(tableRow); oldItemRef = new WeakReference<>(tableRow.getItem()); itemInvalidationListener = o -> { T newItem = ((ObservableValue) 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());

Tenga en cuenta que TableCell tiene una comprobación de igualdad codificada similar, por lo que si la fila personalizada no es suficiente, puede ser necesario utilizar una tabla personalizada con una solución similar (sin embargo, no se ha encontrado un ejemplo donde es necesario)

Supongo que este hilo tiene una muy buena descripción del problema con la actualización de la tabla.

¡Qué ERROR! Aquí hay otra solución …

 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 ); } 

He hecho un SSCCE para mostrar el error . Animo a todos a que lo arreglen de otra manera más elegante porque mi solución es muy fea.

Tengo un caso de uso donde nada más ayudó como la solución de Aubin. Adapte el método y lo cambié eliminando y agregando un elemento a la lista de elementos de las tablas, ya que al final solo funciona de manera confiable con este truco, el alternar visible de la columna hizo el trabajo solo la primera vez.

Lo reporté también en la tarea de Jira: https://javafx-jira.kenai.com/browse/RT-22463

  public  void tableItemsRefresh(final ObservableList 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); } 

Tuve el mismo problema y después de algunas búsquedas esta es mi solución. Descubrí que si las columnas se eliminan y luego se vuelven a agregar, la tabla se actualiza.

 public static  void refreshTableView(final TableView tableView, final List> columns, final List rows) { tableView.getColumns().clear(); tableView.getColumns().addAll(columns); ObservableList list = FXCollections.observableArrayList(rows); tableView.setItems(list); } 

Ejemplo de uso:

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

La solución de user1236048 es correcta, pero el punto clave no se menciona. En las clases de POJO utilizadas para la lista observable de la tabla, no solo tiene que establecer los métodos getter y setter, sino uno nuevo llamado Property. En el tutorial de tablas de Oracle ( http://docs.oracle.com/javafx/2/ui_controls/table-view.htm ), ¡dejaron esa parte clave!

Esto es lo que debería ser la clase 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; } 

}

En lugar de refrescar manualmente, debe usar propiedades notables. Las respuestas de esta pregunta ejemplifican el propósito: SimpleStringProperty y SimpleIntegerProperty TableView JavaFX

Basado en la respuesta 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); } } 

Eche un vistazo a este problema en Jira: https://bugs.openjdk.java.net/browse/JDK-8098085

un comentario 2012-09-20 08:50 dio una solución alternativa que funciona.

 //wierd JavaFX bug reseller_table.setItems(null); reseller_table.layout(); ObservableList data = FXCollections.observableArrayList(User.getResellers()); reseller_table.setItems(data); 

JavaFX8

Estoy agregando un nuevo ítem por un DialogBox. Aquí está mi código.

 ObservableList area = FXCollections.observableArrayList(); 

En initialize () o setApp ()

 this.areaTable.setItems(getAreaData()); 

getAreaData ()

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

Agregar por cuadro de diálogo.

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

Area es un POJO JavaFX ordinario. Espero que esto ayude a alguien.

método initialize ()

 fullNameColumn = new TableColumn("Full name"); fullNameColumn.setCellValueFactory(new PropertyValueFactory("fullName")); usernameColumn = new TableColumn("Username"); usernameColumn.setCellValueFactory(new PropertyValueFactory("test")); emailColumn = new TableColumn("Email"); emailColumn.setCellValueFactory(new PropertyValueFactory("email")); reseller_table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); reseller_table.getColumns().addAll(usernameColumn, fullNameColumn, emailColumn); ObservableList data = FXCollections.observableArrayList(User.getResellers()); reseller_table.setItems(data); 

Clase de usuario (clase Hibernate POJO)

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

método refresh ()

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

Mi solución es similar a la solución de Daniel De León , pero también funciona cuando necesitas ocultar la primera columna (índice 0 en su ejemplo). Por supuesto, podría cambiar el índice en su solución, pero si está reorganizando las columnas, mi solución podría funcionar mejor para usted. La idea es ocultar y mostrar la columna por su nombre en lugar de ocultarla y mostrarla por su índice:

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

Lo mejor es actualizar su tabla en el hilo de actualización de la interfaz de usuario. Sin embargo, también funciona al llamar a updateMyTableView(); después de haber cambiado algo en su tabla, dado que JavaFX parece actualizarse en el hilo de UI de todos modos (no estoy seguro de eso).

 Platform.runLater(new Runnable() { public void run() { updateMyTableView(); } }); 

No estoy seguro de si esto se aplica a su situación, pero publicaré lo que funcionó para mí.

Cambio mi vista de tabla basada en consultas / búsquedas a una base de datos. Por ejemplo, una tabla de base de datos contiene datos del paciente. Mi vista de tabla inicial en mi progtwig contiene todos los pacientes. Luego puedo buscar consultas para Pacientes por nombre y apellido. Uso los resultados de esta consulta para volver a llenar mi lista Observable. Luego reinicié los elementos en la vista de tabla llamando a 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); } 

Los bloques if actualizan la ObservableList con los resultados de la consulta.

El mismo problema aquí, intenté algunas soluciones y lo mejor para mí es lo siguiente:

En initialize-method of controller, cree una lista observable vacía y establézcala en la tabla:

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

En su método de actualización, simplemente use la lista observable, desactívela y agregue los datos actualizados:

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

No es necesario volver a establecer los elementos de la tabla

Siguiendo la respuesta de Daniel De León …

  • Introduje una propiedad ficticia “modelChangedProperty” en mi modelo y
  • Creé un método refresh () en mi modelo que cambia el valor de esa propiedad.
  • En mi controlador, agregué un Listener a la propiedad ficticia que actualiza la vista de tabla.

 /** * Adds a listener to the modelChangedProperty to update the table view */ private void createUpdateWorkAroundListener() { model.modelChangedProperty.addListener( (ObservableValue 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); } 

Sé que esta pregunta tiene 4 años pero tengo el mismo problema, probé las soluciones de arriba y no funcionó. También llamé al método refresh () pero todavía no era mi resultado esperado. Así que publico aquí mi solución tal vez ayude a alguien.

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

Incluso antes de esto, utilicé otra variable en ObeservableList para configurar elementos en la tabla, llamé a esto un “método inmundo”, pero hasta que obtenga una mejor solución, está bien.

He estado tratando de encontrar una forma de actualizar TableView (ScalaFx) durante 3-4 horas. Finalmente recibí una respuesta. Solo quiero publicar mi solución porque perdí muchas horas.

-Para recuperar las filas de la base de datos, solía declarar un método que devuelve ObservableBuffer.

Mi JDBC CLASS

  //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 } 

-Y he creado un objeto TableView.

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

-Y finalmente obtuve una solución. En el botón de actualización, he insertado este código;

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

modelo es la referencia de mi clase de conexión jdbc

 val model = new ScalaJdbcConnectSelect 

Este es el código scalafx, pero le da una idea a javafx

Bien después de buscar todas las soluciones posibles. Intenté borrar los datos primero y luego los agregué a tableView tableView.getItems().clear(); aún eso no resuelve mi problema. Intenté todas las respuestas dadas aquí pero no funcionó para mí y todavía tenía objetos obsoletos en mi mesa como se muestra en la imagen a continuación:

enter image description here

Para solucionarlo, creé una etiqueta DUMMY y usé setGraphic siguiente manera:

enter image description here

更改 C C C 更改 TableColumn 的 able 的 方法 違反 違反 違反 違反 違反 違反 解決 解決 解決 解決 解決 解決 解決 解決 解決 違反 違反 違反 解決 違反 違反 違反 違反 違反 違反 違反 違反 違反 違反 違反 違反 違反 違反 違反 違反.

經過 rastrear código fuente JavaFX 後, 並 並. Error. 利用 Oyente 等 也 也 JFace 中 的 PropiedadChangeSupport 宣告 POJO 內容 最後 最後 最後 最後 最後 最後 最後 最後 最後.

  解決於台灣台北 

He afirmado que el cambio de uso de Column Visable Property no cumple con los requisitos de automatización de enlace de datos.

Después de rastrear el código fuente JavaFX TableView. Nunca descubrí ningún código de problema para el problema de encuadernación de Tableview. Después de hace 4 semanas, cambié el tipo de campo de POJO de DoubleProperty a WritableObjectValue, se solucionó el problema.

  resolve in Taiwan Taipei. 

Código de muestra:

 public class CostAnalytics{ protected WritableObjectValue subtotal=new SimpleObjectProperty();//利用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 getSubtotal() {//利用WritableObjectValue達到自動更新目的,不需要使用個別Column操作setVisable(false)及setVisable(true) return subtotal; } ///... } TableColumn subtotal = new TableColumn( "小計"); subtotal.setCellValueFactory(new Callback, ObservableValue>() { public ObservableValue call( CellDataFeatures p) { WritableObjectValue result = p.getValue().getSubtotal();// //利用WritableObjectValue達到自動更新目的,不需要使用個別Column操作setVisable(false)及setVisable(true) // return (ObservableValue) // result;//利用WritableObjectValue達到自動更新目的,不需要使用個別Column操作setVisable(false)及setVisable(true) // return new // ReadOnlyObjectWrapper(p.getValue().getSubtotal());//造成無法自動更新return (ObservableValue) p.getValue().getSubtotal();// 利用WritableObjectValue達到自動更新目的,不需要使用個別Column操作setVisable(false)及setVisable(true) } });