首页 文章

JavaFX 2.1 TableView刷新项目

提问于
浏览
54

我有这个常见问题,因为它似乎是 . 重置后,我的表视图不会刷新我的项目 . 我检查了数据,这是新的数据 .

I tried multiple solution from internet but no success.

无法重置所有列,因为它添加了一个空的额外(不知道原因)和调整大小只是破坏 .

我的 table 不是 editable . 新数据已更改 .

如果项目和行更改(:|),则刷新数据 .

我只是没有想法 .

目前刷新代码非常简单 .

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

新数据再次正确 . 当我选择tableView时,它返回新的正确Item .

24 回答

  • 1

    基于DanielDeLeó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);
        }
    }
    
  • 0

    在Jira中查看此问题:https://bugs.openjdk.java.net/browse/JDK-8098085

    评论2012-09-20 08:50给出了一个有效的解决方法 .

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

    我有类似的问题与刷新 . 我的解决方案是将 ObservableList 上的操作限制为与 bind() 一起正常工作的操作 .

    假设 ObservableList obsListTableView 的基础列表 .

    然后
    obsList.clear() (继承自 java.util.List<>not update TableView 正确但是 .

    同时调用 setItem(obsList) 确实 not work 触发刷新......但......

    obsList.removeAll(obsList) (由 ObservableList 覆盖) works fine 因为它正确触发了changeEvent .

    使用全新内容重新填充列表,然后按如下方式工作:

    • obsList.removeAll(obsList);

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

    要么

    • obsList.removeAll(obsList);

    • FXCollections.copy(obsList, someSourceList)

    最好的问候Ingo

  • 1

    解决方法:

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

    JavaFX 8u60 开始,您可以使用(假设 tableViewTableView类的实例):

    tableView.refresh();
    

    从文档:

    调用refresh()会强制TableView控件重新创建并重新填充填充控件可视边界所需的单元格 . 换句话说,这会强制TableView更新它向用户显示的内容 . 这在底层数据源以TableView本身未观察到的方式发生更改的情况下非常有用 .

  • 0

    UPDATE:
    最后,在 JavaFX 8u60 中解析了tableview刷新,可以进行早期访问 .


    关于刷新请参阅Updating rows in Tableview .
    关于空白栏,请参阅JavaFx 2 create TableView with single column . 基本上它不是列,即您无法选择单击此空白列项目的项目 . 它只是一个空白的区域,风格像一排 .


    UPDATE: 如果要通过 reseller_table.setItems(data) 更新tableView,则不需要使用 SimpleStringProperty . 如果您只更新一行/项,这将非常有用 . 以下是刷新表数据的完整示例:

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

    注意

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

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

    几乎相同 . 因此,当表刷新时,我第一次用表填充表格 . 它仅用于演示目的 . 我已经在JavaFX 2.1中测试了代码 . 最后,您可以(并且应该)编辑您的问题,通过移动问题答案中的代码片段来改进它 .

  • 6

    我终于找到了一个丑陋的解决方法来刷新所有行 .

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

    oldItems.equals(newItems)似乎有几个独立的问题

    RT-22463:tableView的第一部分即使调用items.clear()也不会更新

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

    这是固定的 . 在设置新列表之前清除旧项清除所有旧状态,从而刷新表 . 任何不起作用的例子都可能是回归 .

    什么仍然无效是重新设置项目而不先清除

    // refresh table
    table.setItems(listEqualToOld);
    

    那个's a problem if the table is showing properties that are not involved into an item'的平等决定(参见RT-22463Aubin's中的例子)并且有希望 - 由RT-39094覆盖

    UPDATERT-39094后者也是固定的,为8u40!应该在几周内冒泡进入ea,推测u12等 .

    技术原因似乎是单元格实现中的相等检查:在实际调用updateItem(T,boolean)之前检查项目的更改是为了修复性能问题 . 合理的,只是硬编码“改变”== old.equals(new)在某些情况下会出现问题 .

    一个对我来说没问题的解决办法(没有正式测试!)是一个自定义TableRow,如果需要进行身份检查,它会跳入:

    /**
     * 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());
    

    请注意,TableCell具有类似的硬编码等式检查,因此如果自定义行不够,则可能需要使用具有类似解决方法的自定义TableCell(尽管没有遇到需要的示例)

  • 1

    我想this thread对表刷新问题有很好的描述 .

  • 3

    什么是BUG!这是另一种解决方法......

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

    我做了SSCCEshow the bug . 我鼓励大家用另一种更优雅的方式解决它,因为我的解决方法非常难看!

  • 2

    我有一个用例,其中没有其他任何帮助作为Aubin的解决方案 . 我调整了方法,并通过删除项目列表中的项目列表并将其添加到表项目列表中来更改它,因为它最终只能通过此hack可靠,列可见切换仅在第一次完成作业 .

    我在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

    我有同样的问题,经过一些搜索,这是我的解决方法 . 我发现如果删除列然后重新添加,则更新表 .

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

    用法示例:

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

    user1236048的解决方案是正确的,但关键点不是可观察列表,您不仅需要设置getter和setter方法,还需要设置一个名为Property的新方法 . 在Oracle的tableview教程(http://docs.oracle.com/javafx/2/ui_controls/table-view.htm)中,他们离开了关键部分!

    这是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;
            }
    

    }

  • 0

    不要手动刷新,而应使用可观察的属性 . 这个问题的答案的例子目的是:SimpleStringProperty and SimpleIntegerProperty TableView JavaFX

  • 0

    我一直试图找到一种刷新tableView(ScalaFx)3-4小时的方法 . 最后我得到了答案 . 我只想发布我的解决方案,因为我已经浪费了几个小时 .

    • 要从数据库中检索行,我用来声明一个返回ObservableBuffer的方法 .

    我的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
    }
    
    • 我创建了一个TableView对象 .
    var table = new TableView[Customer](model.getCustomerDetails)
    table.columns += (customerIdColumn,customerNameColumn,productInstallColumn,serviceDateColumn,
            productNameColumn,phoneNoColumn,detailColumn)
    
    • 最后我得到了解决方案 . 在刷新按钮中,我插入了此代码;
    table.setItems(FXCollections.observableArrayList(model.getCustomerDetails.delegate))
    

    model是我的jdbc连接类的引用

    val model = new ScalaJdbcConnectSelect
    

    这是scalafx代码,但它给javafx一些想法

  • 34

    JavaFX8

    我正在通过DialogBox添加新项目 . 这是我的代码 .

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

    At initialize() or 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;
        }
    }
    

    按对话框添加 .

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

    Area 是一个普通的JavaFX POJO . 希望这有助于某人 .

  • 1

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

    用户类(Hibernate POJO类)

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

    refresh()方法

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

    我的解决方案类似于Daniel De León的解决方法,但是当您需要隐藏第一列(在他的示例中为索引0)时它也有效 . 当然你可以在他的解决方案中更改索引,但如果要重新排列列,我的解决方案可能会更适合您 . 我们的想法是隐藏和显示列的名称,而不是隐藏和显示它的索引:

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

    最好在UI更新线程中更新您的表 . 但是,它也可以通过在您更改表中的内容后调用 updateMyTableView(); 来工作,因为JavaFX似乎无论如何都要在UI线程中更新(不确定) .

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

    我不确定这是否适用于您的情况,但我会发布对我有用的内容 .

    我根据查询/搜索更改我的表视图到数据库 . 例如,数据库表包含患者数据 . 我程序中的初始表视图包含所有患者 . 然后我可以通过firstName和lastName搜索患者的查询 . 我使用此查询的结果来重新填充我的Observable列表 . 然后我通过调用tableview.setItems(observableList)重置tableview中的项:

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

    if块使用查询结果更新ObservableList .

  • -10

    同样的问题,我尝试了一些解决方案,对我来说最好的是:

    在控制器的initialize-method中,创建一个空的observableList并将其设置为表:

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

    在您的update-method中,只需使用observableList,清除它并添加刷新的数据:

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

    没有必要再次设置表的项目

  • 38

    按照DanielDeLeón的回答......

    • 我在我的模型中引入了一个虚拟属性"modelChangedProperty"

    • 在我的模型中创建了一个方法refresh(),用于更改该属性的值 .

    • 在我的控制器中,我向dummy属性添加了一个监听器,用于更新表视图 .

    /**
     * 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);
    }
    
  • 1

    我知道这个问题已经有4年了,但是我遇到了同样的问题,我尝试了上面的解决方案并没有奏效 . 我也称为refresh()方法,但仍然不是我期望的结果 . 所以我在这里发布我的解决方案可能会帮助某人 .

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

    即使在此之前,我在ObeservableList中使用了另一个变量来将项目设置到tableview中,我称之为“污秽方法”,但直到我得到更好的解决方案才行 .

  • 1

    好吧之后寻找所有可能的解决方案 . 首先尝试清除数据然后添加到tableview tableView.getItems().clear(); 仍然无法解决我的问题 . 我尝试了这里给出的所有答案,但没有为我工作,我的表中仍然有陈旧的对象,如下图所示:

    enter image description here

    为了解决这个问题,我创建了一个DUMMY标签并使用 setGraphic 如下:

    enter image description here

  • 60

    我始终认为利用更改的TableColumn的visable属性的方法违反数据绑定的精神,若这是JavaFX的错误的那也早就该接决了,不应该拖到Java8了还不解决 .

    经过跟踪JavaFX的源代码后,并没有发现bug . 利用Listener等方法观察也没有异样 . 也尝试利用JFace中的PropertyChangeSupport方式宣告POJO内容变更也没有效果 . 最后将DoubleProperty改为WritableObjectValue,问提就解决了 .

    解決於台灣台北
    

    我已经坚定使用更改列可见属性不符合数据绑定自动化的目的 .

    之后我跟踪了JavaFX TableView源代码 . 我从未发现Tableview绑定问题的任何问题代码 . 4周前,我将POJO字段的类型从DoubleProperty更改为WritableObjectValue,问题解决了 .

    resolve in Taiwan Taipei.
    

    示例代码:

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

相关问题