JavaFX 2.1 TableView刷新项目

时间:2012-06-16 16:21:46

标签: java javafx tableview javafx-8 fxml

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

我尝试了多种来自互联网的解决方案,但没有成功。

无法重置所有列,因为它会额外添加一个空格(不知道原因),并且调整大小只会破坏。

我的表格不是可编辑。新数据已更改。

如果我更改项目的排序并且行更改(:|),则会刷新数据。

我只是没有想法。

目前刷新代码非常简单。

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

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

26 个答案:

答案 0 :(得分:60)

解决方法:

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

答案 1 :(得分:39)

由于<div class="container-fluid"> <div class="row"> <!-- Button trigger modal --> <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal"> Launch demo modal </button> <!-- Modal --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <h4 class="modal-title" id="myModalLabel">Modal title</h4> </div> <div class="modal-body"> <form class="form-horizontal" id="feedback_form" action="javascript:feedback_submit();" role="form"> <input type="hidden" name="feedback_url" value="http://fmoffice:8080/about" class="form-control"> <input type="hidden" name="feedback_tracking_id" value="" class="form-control"> <div class="form-group"> <div class="form-group" id="feedback_comment_group"> <label class="col-sm-3 control-label" for="feedback_input_comment">Feedback:</label> <div class="col-sm-9 controls"> <textarea id="feedback_input_comment" name="feedback_comment" class="form-control" rows="5" placeholder="Your Feedback"></textarea> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-primary">Send Feedback</button> </div> </div> </div> </form> </div> </div> </div> </div> </div> 可以使用(假设JavaFX 8u60TableView类的实例):

tableView

来自文档:

  

调用refresh()会强制TableView控件重新创建和   重新填充填充视觉边界所必需的细胞   控制。换句话说,这会强制TableView更新它   向用户显示。这在底层的情况下很有用   数据源已经以TableView未观察到的方式发生了变化   本身。

答案 2 :(得分:36)

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

假设ObservableList obsListTableView的基础列表。

然后
obsList.clear()(继承自java.util.List<>无法正确更新 TableView但<。<}

同时致电setItem(obsList) 无效以触发刷新......但......

obsList.removeAll(obsList)(由ObservableList覆盖)正常,因为它会正确触发changeEvent。

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

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

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

最好的问候Ingo

答案 3 :(得分:7)

<强>更新
最后,在 JavaFX 8u60 中解决了tableview刷新问题,可以提前访问。


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


更新:如果您要通过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中测试了代码。最后,您可以(并且应该)编辑您的问题,通过移动问题答案中的代码片段来改进它。

答案 4 :(得分: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);
        }
    });
 }

答案 5 :(得分:3)

oldItems.equals(newItems)

似乎有几个独立的问题

RT-22463的第一部分:即使调用items.clear()

,tableView也不会更新
// refresh table 
table.getItems().clear();
table.setItems(listEqualToOld);    

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

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

// refresh table
table.setItems(listEqualToOld); 

如果表格显示的项目没有涉及项目的平等决策(请参阅RT-22463Aubin's中的示例),并且有希望 - 通过RT-39094

更新RT-39094后者也已修复,为8u40!应该在几周内冒泡进入ea,推测u12等。

技术原因似乎是单元格实现中的相等检查:在实际调用updateItem(T,boolean)之前检查项目的更改是为了修复性能问题。合理的,只是硬编码和改变&#34; == 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(避免遇到示例,其中但是需要的是

答案 6 :(得分:2)

我认为this thread对表刷新问题有很好的描述。

答案 7 :(得分:1)

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

答案 8 :(得分:1)

我一直试图找到一种方法来刷新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提供了一些想法

答案 9 :(得分:1)

<强> JavaFX8

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

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

在initialize()或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。 希望这有助于某人。

答案 10 :(得分:1)

user1236048的解决方案是正确的,但关键点未被调出。在用于表的可观察列表的POJO类中,您不仅需要设置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;
        }

}

答案 11 :(得分: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);

答案 12 :(得分:1)

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

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

答案 13 :(得分:1)

什么是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 );
}

我对SSCCE做了show the bug。我鼓励大家以另一种更优雅的方式解决它,因为我的解决方法非常难看!

答案 14 :(得分:0)

为了刷新我的表,我这样做:

在名为RequisicionesController的ControllerA中,我这样做

@FXML public TableView<Requisiciones>  reqtable;

public TableView<Requisiciones> getReqtable() {
    return reqtable;
}

public void setReqtable(TableView<Requisiciones> reqtable) {
    this.reqtable = reqtable;
}

在FXML加载程序中,我得到了ControllerB,它也名为RevisionReqController

RevisionReqController updateReq = cargarevisionreq.<RevisionReqController>getController();

RequisicionesController.this.setReqtable(selecciondedatosreq());                  
updateReq.setGetmodeltable(RequisicionesController.this.getReqtable());

在我的ControllerB中,我这样做:

public TableView<Requisiciones>  getmodeltable;     

public TableView<Requisiciones> getGetmodeltable() {
    return getmodeltable;
}

public void setGetmodeltable(TableView<Requisiciones> getmodeltable) {
    this.getmodeltable = getmodeltable;
}

然后:

public void refresh () {
    mybutton.setonMouseClicked(e -> {
    ObservableList<Requisiciones> datostabla = FXCollections.observableArrayList();
    try {
        // rest of code

        String Query= " select..";

        PreparedStatement pss =Conexion.prepareStatement(Query);
        ResultSet rs = pss.executeQuery();
        while(rs.next()) {
            datostabla.add(new Requisiciones(
                // al requisiciones data
            ));
        }
        RevisionReqController.this.getGetmodeltable().getItems().clear();
        RevisionReqController.this.getGetmodeltable().setItems(datostabla);
    } catch(Exception ee) {
         //my message here
    }
}

所以在我的controllerA中,我只是用setCellValueFactory加载表,仅此而已。

答案 15 :(得分:0)

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

enter image description here

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

enter image description here

答案 16 :(得分:0)

我知道这个问题已经有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中,我称之为“肮脏的方法”,但直到我得到更好的解决方案是好的。

答案 17 :(得分:0)

您只需要清除表并调用生成表填充的函数即可。

ButtonRefresh.setOnAction((event) -> {
            tacheTable.getItems().clear();
            PopulateTable();
        });

答案 18 :(得分:0)

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

  • 我在模型中引入了一个虚拟属性“modelChangedProperty”和
  • 在我的模型中创建了一个方法refresh(),用于更改该属性的值。
  • 在我的控制器中,我为虚拟属性添加了一个监听器,用于更新表视图。

-

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

答案 19 :(得分:0)

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

在controller的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);

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

答案 20 :(得分: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。

答案 21 :(得分:0)

我的解决方案类似于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();
    }
});

答案 22 :(得分:0)

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

答案 23 :(得分:0)

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

答案 24 :(得分:0)

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

答案 25 :(得分:-10)

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

经过跟踪JavaFX的源代码后,并没有发现bug。利用监听器等方法观察也没有异样。也尝试利用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)
        }

    });