JavaFX 2.1 TableView refresh items

2019-01-03 05:28发布

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.

24条回答
叼着烟拽天下
2楼-- · 2019-01-03 06:13

Workaround:

 tableView.getColumns().get(0).setVisible(false);
 tableView.getColumns().get(0).setVisible(true);
查看更多
欢心
3楼-- · 2019-01-03 06:13

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!

查看更多
Deceive 欺骗
4楼-- · 2019-01-03 06:14

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)

private SimpleStringProperty test;

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

public SimpleStringProperty testProperty() {
  return test;
}

refresh() method

ObservableList<User> data = FXCollections.observableArrayList(User.getResellers());
reseller_table.setItems(data);
查看更多
做个烂人
5楼-- · 2019-01-03 06:17

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


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.


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:

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.

查看更多
倾城 Initia
6楼-- · 2019-01-03 06:17

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

  • I introduced a dummy property "modelChangedProperty" in my model and
  • created a method refresh() in my model that changes the value of that property.
  • 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);
}
查看更多
疯言疯语
7楼-- · 2019-01-03 06:18

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);
        }
    });
 }
查看更多
登录 后发表回答