JavaFX 2.1 TableView刷新项目。

时间:2022-01-14 17:05:30

I have this common issue, as it appears to be. My table view wont refresh my items after I reset them. I have checked the data and it's the new one.

我有一个共同的问题,似乎是这样。我的表视图在重置后不会刷新我的项目。我查过数据了,是新的。

I tried multiple solution from internet but no success.

我从网上尝试了多种解决方案,但没有成功。

Can't reset all the columns because it adds one empty one extra (dont know why) and the resize just breakes.

不能重置所有的列,因为它添加一个空的一个额外的(不知道为什么)和调整大小。

My table is not editable. The new data is changed.

我的桌子不是可编辑的。新的数据被改变了。

The data is refreshed if I change the ordering of the items and the rows change (:|).

如果我更改项的顺序和行更改(:|),则会刷新数据。

I'm just left without ideas.

我只是没有想法。

At the moment the refresh code is pretty simple.

现在,刷新代码非常简单。

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

Again the new data is correct. When I make an selection to the tableView it returns the new correct Item.

新数据再次正确。当我对tableView进行选择时,它会返回新的正确项。

23 个解决方案

#1


32  

I had a similar problem with refreshing. My solution was to restrict the operations on the ObservableList to those which work correctly with bind().

我有一个类似的问题,让人耳目一新。我的解决方案是将可观察列表上的操作限制为正确使用bind()的操作。

Assume ObservableList obsList is the underlying list for the TableView.

假设ObservableList强迫症是TableView的基础列表。

Then
obsList.clear() (inherited from java.util.List<>) will not update the tableView correctly but.

然后obsList.clear()(继承自java.util.List<>)将不会正确地更新tableView,但是。

Also calling setItem(obsList) did not work to trigger a refresh...but...

也叫setItem(着迷的)没有激活刷新…但是…

obsList.removeAll(obsList) (overwritten by ObservableList) works fine because it fires the changeEvent correctly :-)

removeall(被观察列表覆盖)运行良好,因为它正确地触发了changeEvent:-)

Refilling a list with completely new content then works as follows:

重新填写一个包含全新内容的列表,然后工作如下:

  • obsList.removeAll(obsList);
  • obsList.removeAll(obsList);
  • obsList.add(...); //e.g. in a loop...
  • obsList.add(…);/ /。在一个循环中……

or

  • obsList.removeAll(obsList);
  • obsList.removeAll(obsList);
  • FXCollections.copy(obsList, someSourceList)
  • FXCollections。复制(obsList someSourceList)

Best regards Ingo

Ingo问好

#2


56  

Workaround:

处理:

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

#3


22  

Since JavaFX 8u60 you can use(assuming tableView is an instance of TableView class):

既然JavaFX 8u60可以使用(假设tableView是tableView类的实例):

tableView.refresh();

From the documentation:

从文档:

Calling refresh() forces the TableView control to recreate and repopulate the cells necessary to populate the visual bounds of the control. In other words, this forces the TableView to update what it is showing to the user. This is useful in cases where the underlying data source has changed in a way that is not observed by the TableView itself.

调用refresh()迫使TableView控件重新创建和重新填充所需的单元,以填充控件的可视范围。换句话说,这迫使TableView更新它向用户显示的内容。在底层数据源以一种未被TableView本身观察到的方式发生变化的情况下,这是很有用的。

#4


7  

UPDATE:
Finally tableview refreshing is resolved in JavaFX 8u60, which is available for early access.

更新:最后,tableview刷新在javafx8u60中得到解决,它可以用于早期访问。


About refreshing see the Updating rows in Tableview.
And about the blank column see the JavaFx 2 create TableView with single column. Basically it is not a column, i.e. you cannot select the item clicking on this blank column items. It is just a blank area styled like a row.

关于刷新,请参阅Tableview中的更新行。在空白列中,可以看到JavaFx 2用单列创建TableView。基本上它不是一个列,也就是说,您不能选择单击这个空白列项目的项。它只是一个像一行的空白区域。


UPDATE: If you are updating the tableView via reseller_table.setItems(data) then you don't need to use SimpleStringProperty. It would be useful if you were updating one row/item only. Here is a working full example of refreshing the table data:

更新:如果您通过reseller_table.setItems(数据)更新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);
    }
}

Note that

请注意,

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

and

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

are almost equivalent. So I used the one to fill the table for the first time and other when the table is refreshed. It is for demo purposes only. I have tested the code in JavaFX 2.1. And finally, you can (and should) edit your question to improve it by moving the code pieces in your answer to your question.

几乎是等价的。因此,我第一次使用这个表来填充表,当表被刷新时,另一个填充表。它仅用于演示目的。我已经在JavaFX 2.1中测试了代码。最后,您可以(也应该)编辑您的问题,通过将代码块移到您的问题的答案中来改进它。

#5


6  

I finally found an ugly workaround to refresh all rows.

我终于发现了一个很难看的方法来刷新所有的行。

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


2  

There seem to be several separate issues around oldItems.equals(newItems)

在oldItems.equals(newItems)中,似乎存在几个不同的问题

The first part of RT-22463: tableView won't update even if calling items.clear()

RT-22463的第一部分:tableView即使调用项也不会更新。

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

that's fixed. Clearing out the old items before setting a new list clears out all old state, thus refreshing the table. Any example where this doesn't work might be a regression.

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

What's still not working is re-setting items without clearing first

仍然不工作的是重新设置项目而不首先清除!

// refresh table
table.setItems(listEqualToOld); 

That's a problem if the table is showing properties that are not involved into an item's equal decision (see example in RT-22463 or Aubin's) and covered - hopefully - by RT-39094

这是一个问题,如果表显示的属性没有涉及到项目的相同决策(参见RT-22463或Aubin的例子),并希望通过RT-39094进行覆盖。

UPDATE: RT-39094 the latter is fixed as well, for 8u40! Should bubble up into the ea in a couple of weeks, speculating on u12 or such.

更新:RT-39094后者也是固定的,用于8u40!应该在几周内泡在ea里,推测u12。

The technical reason seems to be an equality check in cell's implementation: checking for changes of the item before actually calling updateItem(T, boolean) was introduced to fix performance problems. Reasonable, just to hard-code "change" == old.equals(new) poses problems in some contexts.

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

A work-around that's fine for me (no formal testing!) is a custom TableRow which jumps in if identity check is required:

一个适合我的工作(没有正式的测试!)是一个自定义的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());

Note that TableCell has a similar hard-coded equality check, so if the custom row doesn't suffice it might be necessary to use a custom TableCell with a similar workaround (haven't run into an example where that's needed, though)

注意,TableCell有一个类似的硬编码的等式检查,所以如果自定义行不够,那么可能需要使用一个类似的解决方案来使用自定义的TableCell(尽管还没有遇到需要的例子)

#7


2  

I suppose this thread has a very good description of the problem with table refresh.

我想这个线程对表刷新的问题有很好的描述。

#8


1  

What a BUG ! Here is another workaround...

什么一个错误!这是另一个解决方案…

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

I've done a SSCCE to show the bug. I encourage everyone to fix it by another more elegant way because my workaround is very ugly!

我做了一个SSCCE来显示这个bug。我鼓励大家用另一种更优雅的方式来修复它,因为我的工作很丑!

#9


1  

I have an use case where nothing else helped as the solution from Aubin. I adapted the method and changed it by removing and adding an item to the tables' item list as it works in the end only reliable with this hack, the column visible toggle did the job only the first time.

我有一个用例,在这个例子中,没有任何其他东西可以作为Aubin的解决方案。我修改了这个方法,并将其删除,并将一个项添加到表的项目列表中,因为它在最后只使用了这个hack,而这个列可见toggle只在第一次完成了任务。

I reported it also in the Jira task: https://javafx-jira.kenai.com/browse/RT-22463

我也在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);
   } 

#10


1  

I had the same problem and after some search this is my workaround. I found that if the columns are removed and then re-added the table is updated.

我遇到了同样的问题,经过一些搜索,这是我的工作。我发现,如果删除列,然后重新添加表,就会更新。

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


Example of usage:

使用的例子:

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

#11


1  

The solution by user1236048 is correct, but the key point isn't called out. In your POJO classes used for the table's observable list, you not only have to set getter and setter methods, but a new one called Property. In Oracle's tableview tutorial (http://docs.oracle.com/javafx/2/ui_controls/table-view.htm), they left that key part off!

user1236048的解决方案是正确的,但关键问题并没有被取消。在用于表可观察列表的POJO类中,您不仅需要设置getter和setter方法,还必须设置一个名为Property的新方法。在Oracle的tableview教程(http://docs.oracle.com/javafx/2/ui_controls/table-view.htm)中,他们将关键部分关闭了!

Here's what the Person class should look like:

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

}

}

#12


1  

Instead of refreshing manually you should use observeable properties. The answers of this question examples the purpose: SimpleStringProperty and SimpleIntegerProperty TableView JavaFX

您应该使用可观察的属性,而不是手动刷新。这个问题的答案示例的目的是:SimpleStringProperty和SimpleIntegerProperty TableView JavaFX。

#13


1  

Based on Daniel De León's answer

根据丹尼尔·德莱昂的回答。

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

#14


1  

Take a look at this issue in Jira: https://bugs.openjdk.java.net/browse/JDK-8098085

查看Jira中的这个问题:https://bugs.openjdk.java.net/browse/JDK-8098085。

a comment 2012-09-20 08:50 gave a workaround that works.

发表评论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);

#15


1  

JavaFX8

JavaFX8

I'm adding new Item by a DialogBox. Here is my code.

我正在通过对话框添加新项。这是我的代码。

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

At initialize() or setApp()

在初始化()或setApp()

this.areaTable.setItems(getAreaData());

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

Add by dialog box.

添加对话框。

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

}

Area is an ordinary JavaFX POJO. Hope this helps someone.

区域是一个普通的JavaFX POJO。希望这可以帮助别人。

#16


0  

initialize() method

初始化()方法

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

User Class (Hibernate POJO Class)

用户类(Hibernate POJO类)

private SimpleStringProperty test;

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

public SimpleStringProperty testProperty() {
  return test;
}

refresh() method

refresh()方法

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

#17


0  

My solution is similar to the the workaround of Daniel De León, but it also works when you need to hide the first column (index 0 in his example). Of course you could just change the index in his solution, but if you are rearranging the columns, my solution might work better for you. The idea is to hide and show the column by its name instead of hiding and showing it by its index:

我的解决方案类似于Daniel De Leon的解决方案,但是当您需要隐藏第一个列(在他的示例中为索引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);
            }
        }
    }
}

It's best to update your table in the UI update thread. However, it also works by just calling updateMyTableView(); after you've changed something in your table, since JavaFX seem to update in the UI thread anyway (not sure about that).

最好在UI更新线程中更新您的表。但是,它也只调用updateMyTableView();在您更改了表中的内容之后,因为JavaFX似乎在UI线程中更新了(不确定)。

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

#18


0  

I am not sure if this applies to your situation, but I will post what worked for me.

我不确定这是否适用于你的情况,但我会发布我的工作。

I change my table view based on queries / searches to a database. For example, a database table contains Patient data. My initial table view in my program contains all Patients. I can then search query for Patients by firstName and lastName. I use the results of this query to repopulate my Observable list. Then I reset the items in the tableview by calling tableview.setItems(observableList):

我根据对数据库的查询/搜索更改表视图。例如,数据库表包含患者数据。我的程序中的初始表视图包含所有的患者。然后,我可以通过firstName和lastName搜索查询。我使用这个查询的结果来重新填充我的可观察列表。然后我通过调用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);
}

The if blocks update the ObservableList with the query results.

if块用查询结果更新可观察列表。

#19


0  

Same problem here, i tried some solutions and the best for me is following:

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

In initialize-method of controller, create an empty observableList and set it to the table:

在控制器的初始化方法中,创建一个空的可观察列表并将其设置为表:

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

In your update-method, just use the observableList, clear it and add the refreshed data:

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

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

It's not necessary to set the items of the table again

没有必要再次设置表中的项。

#20


0  

Following the answer of Daniel De León ...

根据Daniel De Leon的回答……

  • I introduced a dummy property "modelChangedProperty" in my model and
  • 我在模型中引入了一个虚拟属性“modelChangedProperty”。
  • created a method refresh() in my model that changes the value of that property.
  • 在我的模型中创建了一个方法refresh(),它改变了该属性的值。
  • In my controller I added a Listener to the dummy property that updates the table view.
  • 在我的控制器中,我添加了一个侦听器到更新表视图的虚拟属性。

-

- - - - - -

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

#21


0  

I know that this question is 4 years old but I have the same problem, I tried the solutions from above and didn't worked. I also called refresh() method but still not my expected result. So I post here my solution maybe will help someone.

我知道这个问题已经有4年了,但是我有同样的问题,我尝试了上面的解决方案,但是没有成功。我也调用refresh()方法,但仍然不是我的预期结果。所以我在这里张贴我的解决方案也许会帮助别人。

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

Even that before of this I used another variable in ObeservableList for setting items into the tableview, I call this a "filthy method" but until I get a better solution is ok.

甚至在这之前,我还在肥胖列表中使用了另一个变量来将项目设置为tableview,我把它称为“肮脏的方法”,但是在我得到更好的解决方案之前。

#22


0  

I have been trying to find a way to refresh the tableView(ScalaFx) for 3-4 hours. Finally I got a answer. I just want to publish my solution because of i wasted already hours.

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

-To retrieve the rows from database, i used to declare a method which returns ObservableBuffer.

为了从数据库中检索行,我使用了一个返回可观察缓冲区的方法。

My JDBC CLASS

我的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
}

-And I have created a TableView object.

-我创建了一个TableView对象。

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

-And Finally i got solution. In the refresh button, i have inserted this code;

最后我得到了解决方案。在refresh按钮中,我插入了这个代码;

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

model is the reference of my jdbc connection class

模型是我的jdbc连接类的引用。

val model = new ScalaJdbcConnectSelect

This is the scalafx codes but it gives some idea to javafx

这是scalafx代码,但它给javafx提供了一些想法。

#23


-10  

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

我始終認為利用更改TableColumn的视觉屬性的方法違反数据绑定的精神,若這是JavaFX的错误那也早就該接決了,不應該拖到Java8了還不解決。

經過trace JavaFX 的source code後,並沒有發現bug。利用Listener等方法觀察也沒有異樣。也嘗試利用JFace中的PropertyChangeSupport方式宣告POJO內容變更也沒有效果。最後將DoubleProperty 改為WritableObjectValue,問提就解決了。

經過跟踪JavaFX的源代码後並沒有發現bug。利用侦听器等方法觀察也沒有異樣。也嘗試利用JFace中的PropertyChangeSupport方式宣告POJO內容變更也沒有效果。最後將DoubleProperty改為WritableObjectValue,問提就解決了。

                                                           解決於台灣台北

I had firmed use change Column Visable Property is not conform data binding automation purpose.

我已确定使用更改列可维持性属性不符合数据绑定自动化的目的。

After I traced JavaFX TableView source code. I never discovered any problem code for Tableview binding issue. After 4 weeks ago, I changed POJO field's type from DoubleProperty to WritableObjectValue, problem was solved.

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

                                               resolve in * Taipei.

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

    });

#1


32  

I had a similar problem with refreshing. My solution was to restrict the operations on the ObservableList to those which work correctly with bind().

我有一个类似的问题,让人耳目一新。我的解决方案是将可观察列表上的操作限制为正确使用bind()的操作。

Assume ObservableList obsList is the underlying list for the TableView.

假设ObservableList强迫症是TableView的基础列表。

Then
obsList.clear() (inherited from java.util.List<>) will not update the tableView correctly but.

然后obsList.clear()(继承自java.util.List<>)将不会正确地更新tableView,但是。

Also calling setItem(obsList) did not work to trigger a refresh...but...

也叫setItem(着迷的)没有激活刷新…但是…

obsList.removeAll(obsList) (overwritten by ObservableList) works fine because it fires the changeEvent correctly :-)

removeall(被观察列表覆盖)运行良好,因为它正确地触发了changeEvent:-)

Refilling a list with completely new content then works as follows:

重新填写一个包含全新内容的列表,然后工作如下:

  • obsList.removeAll(obsList);
  • obsList.removeAll(obsList);
  • obsList.add(...); //e.g. in a loop...
  • obsList.add(…);/ /。在一个循环中……

or

  • obsList.removeAll(obsList);
  • obsList.removeAll(obsList);
  • FXCollections.copy(obsList, someSourceList)
  • FXCollections。复制(obsList someSourceList)

Best regards Ingo

Ingo问好

#2


56  

Workaround:

处理:

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

#3


22  

Since JavaFX 8u60 you can use(assuming tableView is an instance of TableView class):

既然JavaFX 8u60可以使用(假设tableView是tableView类的实例):

tableView.refresh();

From the documentation:

从文档:

Calling refresh() forces the TableView control to recreate and repopulate the cells necessary to populate the visual bounds of the control. In other words, this forces the TableView to update what it is showing to the user. This is useful in cases where the underlying data source has changed in a way that is not observed by the TableView itself.

调用refresh()迫使TableView控件重新创建和重新填充所需的单元,以填充控件的可视范围。换句话说,这迫使TableView更新它向用户显示的内容。在底层数据源以一种未被TableView本身观察到的方式发生变化的情况下,这是很有用的。

#4


7  

UPDATE:
Finally tableview refreshing is resolved in JavaFX 8u60, which is available for early access.

更新:最后,tableview刷新在javafx8u60中得到解决,它可以用于早期访问。


About refreshing see the Updating rows in Tableview.
And about the blank column see the JavaFx 2 create TableView with single column. Basically it is not a column, i.e. you cannot select the item clicking on this blank column items. It is just a blank area styled like a row.

关于刷新,请参阅Tableview中的更新行。在空白列中,可以看到JavaFx 2用单列创建TableView。基本上它不是一个列,也就是说,您不能选择单击这个空白列项目的项。它只是一个像一行的空白区域。


UPDATE: If you are updating the tableView via reseller_table.setItems(data) then you don't need to use SimpleStringProperty. It would be useful if you were updating one row/item only. Here is a working full example of refreshing the table data:

更新:如果您通过reseller_table.setItems(数据)更新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);
    }
}

Note that

请注意,

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

and

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

are almost equivalent. So I used the one to fill the table for the first time and other when the table is refreshed. It is for demo purposes only. I have tested the code in JavaFX 2.1. And finally, you can (and should) edit your question to improve it by moving the code pieces in your answer to your question.

几乎是等价的。因此,我第一次使用这个表来填充表,当表被刷新时,另一个填充表。它仅用于演示目的。我已经在JavaFX 2.1中测试了代码。最后,您可以(也应该)编辑您的问题,通过将代码块移到您的问题的答案中来改进它。

#5


6  

I finally found an ugly workaround to refresh all rows.

我终于发现了一个很难看的方法来刷新所有的行。

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


2  

There seem to be several separate issues around oldItems.equals(newItems)

在oldItems.equals(newItems)中,似乎存在几个不同的问题

The first part of RT-22463: tableView won't update even if calling items.clear()

RT-22463的第一部分:tableView即使调用项也不会更新。

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

that's fixed. Clearing out the old items before setting a new list clears out all old state, thus refreshing the table. Any example where this doesn't work might be a regression.

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

What's still not working is re-setting items without clearing first

仍然不工作的是重新设置项目而不首先清除!

// refresh table
table.setItems(listEqualToOld); 

That's a problem if the table is showing properties that are not involved into an item's equal decision (see example in RT-22463 or Aubin's) and covered - hopefully - by RT-39094

这是一个问题,如果表显示的属性没有涉及到项目的相同决策(参见RT-22463或Aubin的例子),并希望通过RT-39094进行覆盖。

UPDATE: RT-39094 the latter is fixed as well, for 8u40! Should bubble up into the ea in a couple of weeks, speculating on u12 or such.

更新:RT-39094后者也是固定的,用于8u40!应该在几周内泡在ea里,推测u12。

The technical reason seems to be an equality check in cell's implementation: checking for changes of the item before actually calling updateItem(T, boolean) was introduced to fix performance problems. Reasonable, just to hard-code "change" == old.equals(new) poses problems in some contexts.

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

A work-around that's fine for me (no formal testing!) is a custom TableRow which jumps in if identity check is required:

一个适合我的工作(没有正式的测试!)是一个自定义的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());

Note that TableCell has a similar hard-coded equality check, so if the custom row doesn't suffice it might be necessary to use a custom TableCell with a similar workaround (haven't run into an example where that's needed, though)

注意,TableCell有一个类似的硬编码的等式检查,所以如果自定义行不够,那么可能需要使用一个类似的解决方案来使用自定义的TableCell(尽管还没有遇到需要的例子)

#7


2  

I suppose this thread has a very good description of the problem with table refresh.

我想这个线程对表刷新的问题有很好的描述。

#8


1  

What a BUG ! Here is another workaround...

什么一个错误!这是另一个解决方案…

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

I've done a SSCCE to show the bug. I encourage everyone to fix it by another more elegant way because my workaround is very ugly!

我做了一个SSCCE来显示这个bug。我鼓励大家用另一种更优雅的方式来修复它,因为我的工作很丑!

#9


1  

I have an use case where nothing else helped as the solution from Aubin. I adapted the method and changed it by removing and adding an item to the tables' item list as it works in the end only reliable with this hack, the column visible toggle did the job only the first time.

我有一个用例,在这个例子中,没有任何其他东西可以作为Aubin的解决方案。我修改了这个方法,并将其删除,并将一个项添加到表的项目列表中,因为它在最后只使用了这个hack,而这个列可见toggle只在第一次完成了任务。

I reported it also in the Jira task: https://javafx-jira.kenai.com/browse/RT-22463

我也在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);
   } 

#10


1  

I had the same problem and after some search this is my workaround. I found that if the columns are removed and then re-added the table is updated.

我遇到了同样的问题,经过一些搜索,这是我的工作。我发现,如果删除列,然后重新添加表,就会更新。

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


Example of usage:

使用的例子:

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

#11


1  

The solution by user1236048 is correct, but the key point isn't called out. In your POJO classes used for the table's observable list, you not only have to set getter and setter methods, but a new one called Property. In Oracle's tableview tutorial (http://docs.oracle.com/javafx/2/ui_controls/table-view.htm), they left that key part off!

user1236048的解决方案是正确的,但关键问题并没有被取消。在用于表可观察列表的POJO类中,您不仅需要设置getter和setter方法,还必须设置一个名为Property的新方法。在Oracle的tableview教程(http://docs.oracle.com/javafx/2/ui_controls/table-view.htm)中,他们将关键部分关闭了!

Here's what the Person class should look like:

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

}

}

#12


1  

Instead of refreshing manually you should use observeable properties. The answers of this question examples the purpose: SimpleStringProperty and SimpleIntegerProperty TableView JavaFX

您应该使用可观察的属性,而不是手动刷新。这个问题的答案示例的目的是:SimpleStringProperty和SimpleIntegerProperty TableView JavaFX。

#13


1  

Based on Daniel De León's answer

根据丹尼尔·德莱昂的回答。

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

#14


1  

Take a look at this issue in Jira: https://bugs.openjdk.java.net/browse/JDK-8098085

查看Jira中的这个问题:https://bugs.openjdk.java.net/browse/JDK-8098085。

a comment 2012-09-20 08:50 gave a workaround that works.

发表评论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);

#15


1  

JavaFX8

JavaFX8

I'm adding new Item by a DialogBox. Here is my code.

我正在通过对话框添加新项。这是我的代码。

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

At initialize() or setApp()

在初始化()或setApp()

this.areaTable.setItems(getAreaData());

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

Add by dialog box.

添加对话框。

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

}

Area is an ordinary JavaFX POJO. Hope this helps someone.

区域是一个普通的JavaFX POJO。希望这可以帮助别人。

#16


0  

initialize() method

初始化()方法

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

User Class (Hibernate POJO Class)

用户类(Hibernate POJO类)

private SimpleStringProperty test;

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

public SimpleStringProperty testProperty() {
  return test;
}

refresh() method

refresh()方法

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

#17


0  

My solution is similar to the the workaround of Daniel De León, but it also works when you need to hide the first column (index 0 in his example). Of course you could just change the index in his solution, but if you are rearranging the columns, my solution might work better for you. The idea is to hide and show the column by its name instead of hiding and showing it by its index:

我的解决方案类似于Daniel De Leon的解决方案,但是当您需要隐藏第一个列(在他的示例中为索引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);
            }
        }
    }
}

It's best to update your table in the UI update thread. However, it also works by just calling updateMyTableView(); after you've changed something in your table, since JavaFX seem to update in the UI thread anyway (not sure about that).

最好在UI更新线程中更新您的表。但是,它也只调用updateMyTableView();在您更改了表中的内容之后,因为JavaFX似乎在UI线程中更新了(不确定)。

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

#18


0  

I am not sure if this applies to your situation, but I will post what worked for me.

我不确定这是否适用于你的情况,但我会发布我的工作。

I change my table view based on queries / searches to a database. For example, a database table contains Patient data. My initial table view in my program contains all Patients. I can then search query for Patients by firstName and lastName. I use the results of this query to repopulate my Observable list. Then I reset the items in the tableview by calling tableview.setItems(observableList):

我根据对数据库的查询/搜索更改表视图。例如,数据库表包含患者数据。我的程序中的初始表视图包含所有的患者。然后,我可以通过firstName和lastName搜索查询。我使用这个查询的结果来重新填充我的可观察列表。然后我通过调用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);
}

The if blocks update the ObservableList with the query results.

if块用查询结果更新可观察列表。

#19


0  

Same problem here, i tried some solutions and the best for me is following:

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

In initialize-method of controller, create an empty observableList and set it to the table:

在控制器的初始化方法中,创建一个空的可观察列表并将其设置为表:

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

In your update-method, just use the observableList, clear it and add the refreshed data:

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

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

It's not necessary to set the items of the table again

没有必要再次设置表中的项。

#20


0  

Following the answer of Daniel De León ...

根据Daniel De Leon的回答……

  • I introduced a dummy property "modelChangedProperty" in my model and
  • 我在模型中引入了一个虚拟属性“modelChangedProperty”。
  • created a method refresh() in my model that changes the value of that property.
  • 在我的模型中创建了一个方法refresh(),它改变了该属性的值。
  • In my controller I added a Listener to the dummy property that updates the table view.
  • 在我的控制器中,我添加了一个侦听器到更新表视图的虚拟属性。

-

- - - - - -

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

#21


0  

I know that this question is 4 years old but I have the same problem, I tried the solutions from above and didn't worked. I also called refresh() method but still not my expected result. So I post here my solution maybe will help someone.

我知道这个问题已经有4年了,但是我有同样的问题,我尝试了上面的解决方案,但是没有成功。我也调用refresh()方法,但仍然不是我的预期结果。所以我在这里张贴我的解决方案也许会帮助别人。

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

Even that before of this I used another variable in ObeservableList for setting items into the tableview, I call this a "filthy method" but until I get a better solution is ok.

甚至在这之前,我还在肥胖列表中使用了另一个变量来将项目设置为tableview,我把它称为“肮脏的方法”,但是在我得到更好的解决方案之前。

#22


0  

I have been trying to find a way to refresh the tableView(ScalaFx) for 3-4 hours. Finally I got a answer. I just want to publish my solution because of i wasted already hours.

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

-To retrieve the rows from database, i used to declare a method which returns ObservableBuffer.

为了从数据库中检索行,我使用了一个返回可观察缓冲区的方法。

My JDBC CLASS

我的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
}

-And I have created a TableView object.

-我创建了一个TableView对象。

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

-And Finally i got solution. In the refresh button, i have inserted this code;

最后我得到了解决方案。在refresh按钮中,我插入了这个代码;

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

model is the reference of my jdbc connection class

模型是我的jdbc连接类的引用。

val model = new ScalaJdbcConnectSelect

This is the scalafx codes but it gives some idea to javafx

这是scalafx代码,但它给javafx提供了一些想法。

#23


-10  

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

我始終認為利用更改TableColumn的视觉屬性的方法違反数据绑定的精神,若這是JavaFX的错误那也早就該接決了,不應該拖到Java8了還不解決。

經過trace JavaFX 的source code後,並沒有發現bug。利用Listener等方法觀察也沒有異樣。也嘗試利用JFace中的PropertyChangeSupport方式宣告POJO內容變更也沒有效果。最後將DoubleProperty 改為WritableObjectValue,問提就解決了。

經過跟踪JavaFX的源代码後並沒有發現bug。利用侦听器等方法觀察也沒有異樣。也嘗試利用JFace中的PropertyChangeSupport方式宣告POJO內容變更也沒有效果。最後將DoubleProperty改為WritableObjectValue,問提就解決了。

                                                           解決於台灣台北

I had firmed use change Column Visable Property is not conform data binding automation purpose.

我已确定使用更改列可维持性属性不符合数据绑定自动化的目的。

After I traced JavaFX TableView source code. I never discovered any problem code for Tableview binding issue. After 4 weeks ago, I changed POJO field's type from DoubleProperty to WritableObjectValue, problem was solved.

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

                                               resolve in * Taipei.

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

    });