Java TreeTableColumn自定义setCellFactory未立即更新UI的问题

Java TreeTableColumn自定义setCellFactory未立即更新UI的问题,java,javafx,Java,Javafx,我有一个TreeTableColumn树etablecolumn。我设置了一个自定义单元格工厂,在这里我将组合框的宽度设置为与列本身相同的宽度。在我开始上下滚动TreeTableView之前,UI本身不会更新 希望下面的代码是所有相关的代码 TreeTableColumn<ProjectView, ComboBox> treeTableColumn = new TreeTableColumn<>("Description"); treeTableColumn.setCel

我有一个
TreeTableColumn树etablecolumn
。我设置了一个自定义单元格工厂,在这里我将组合框的宽度设置为与列本身相同的宽度。在我开始上下滚动TreeTableView之前,UI本身不会更新

希望下面的代码是所有相关的代码

TreeTableColumn<ProjectView, ComboBox> treeTableColumn = new TreeTableColumn<>("Description");
treeTableColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("comboBox"));
treeTableColumn.setCellFactory(col -> {
            TreeTableCell<ProjectView, ComboBox> cell = new TreeTableCell<ProjectView, ComboBox>() {
                @Override
                public void updateItem(ComboBox item, boolean empty) {
                    super.updateItem(item, empty);
                    ComboBox newItem = new ComboBox();
                    newItem.setMinWidth(this.getWidth());                   
                    this.setGraphic(newItem);                   
                }

            };
            return cell;
        });

treeTableView.getColumns().add(treeTableColumn);
如您所见,这是一个非常简单的单元值工厂实现。我已经删除了尽可能多的额外代码,试图找出问题所在,但即使使用此实现,最初显示的组合框的宽度也都不正确。一旦开始在TreeTableView中上下滚动,单元格内的组合框将开始使用正确的宽度正确显示

我看到过几篇处理类似问题的文章,但它们的修复似乎都不起作用。 我试着调用refresh,试着切换col和tableview的可见性。我已经确保调用了super方法,并且setGraphics总是在更新方法中设置,我在setCellFactory方法中重写了更新方法。我肯定我错过了什么,但我就是看不到。任何帮助都将不胜感激

编辑:

下面是一个再现这个问题的例子。我应该注意的是,在发布这篇文章之后,我发现如果我将更新包装在Platform.runLater线程中,它会工作,但这并不是正确的方法

 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package javafxapplication;

import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;


public class JavaFXApplication extends Application {

    @Override
    public void start(Stage primaryStage) {

        TreeTableView treeTableView = new TreeTableView();

        treeTableView.getColumns().clear();

        TreeTableColumn<ProjectView, ComboBox> treeTableColumn = new TreeTableColumn<>("Dependencies");

        treeTableColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("comboBox"));

        treeTableColumn.setCellFactory(col -> {
            TreeTableCell<ProjectView, ComboBox> cell = new TreeTableCell<ProjectView, ComboBox>() {
                @Override
                public void updateItem(ComboBox item, boolean empty) {
                    super.updateItem(item, empty);
                    ComboBox newItem = new ComboBox();
                    newItem.getItems().add("Test");
                    newItem.setMinWidth(this.getWidth());
                    this.setGraphic(newItem);
                }

            };
            return cell;
        });

        List<ProjectView> projectList = new ArrayList<>();

        for (int i = 0; i < 25; i++) {
            projectList.add(new ProjectView());
        }

        treeTableView.getColumns().add(treeTableColumn);

        TreeItem treeRoot = new TreeItem();
        projectList.stream().filter((p) -> (p != null)).forEachOrdered((ProjectView p) -> {
            TreeItem project = new TreeItem(p);
            treeRoot.getChildren().add(project);
        });
        treeTableView.setShowRoot(false);
        treeTableView.setRoot(treeRoot);

        StackPane root = new StackPane();

        root.getChildren().add(treeTableView);
        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    public static class ProjectView {

        public ProjectView() {
        }

        public ComboBox getComboBox() {
            ComboBox cb = new ComboBox();
            cb.getItems().add("Test");
            return cb;
        }
    }

}
*要更改此许可证标题,请在项目属性中选择许可证标题。
*要更改此模板文件,请选择工具|模板
*然后在编辑器中打开模板。
*/
应用软件包;
导入java.util.ArrayList;
导入java.util.List;
导入javafx.application.application;
导入javafx.scene.scene;
导入javafx.scene.control.ComboBox;
导入javafx.scene.control.TreeItem;
导入javafx.scene.control.TreeTableCell;
导入javafx.scene.control.TreeTableColumn;
导入javafx.scene.control.TreeTableView;
导入javafx.scene.control.cell.TreeItemPropertyValueFactory;
导入javafx.scene.layout.StackPane;
导入javafx.stage.stage;
公共类JavaFXApplication扩展了应用程序{
@凌驾
公共无效开始(阶段primaryStage){
TreeTableView TreeTableView=新的TreeTableView();
treeTableView.getColumns().clear();
TreeTableColumn TreeTableColumn=新的TreeTableColumn(“依赖项”);
setCellValueFactory(新的TreeItemPropertyValueFactory(“组合框”);
treeTableColumn.setCellFactory(列->{
TreeTableCell=新的TreeTableCell(){
@凌驾
public void updateItem(组合框项,布尔空){
super.updateItem(项,空);
ComboBox newItem=新ComboBox();
newItem.getItems()添加(“测试”);
newItem.setMinWidth(this.getWidth());
此.setGraphic(newItem);
}
};
返回单元;
});
List projectList=new ArrayList();
对于(int i=0;i<25;i++){
添加(新项目视图());
}
treeTableView.getColumns().add(treeTableColumn);
TreeItem treeRoot=新的TreeItem();
projectList.stream().filter((p)->(p!=null)).forEachOrdered((ProjectView p)->{
TreeItem项目=新的TreeItem(p);
treeRoot.getChildren().add(项目);
});
treeTableView.setShowRoot(false);
treeTableView.setRoot(treeRoot);
StackPane root=新的StackPane();
root.getChildren().add(treeTableView);
场景=新场景(根,300,250);
setTitle(“你好,世界!”);
初级阶段。场景(场景);
primaryStage.show();
}
/**
*@param指定命令行参数
*/
公共静态void main(字符串[]args){
发射(args);
}
公共静态类ProjectView{
公共项目视图(){
}
公共组合框getComboBox(){
ComboBox cb=新ComboBox();
cb.getItems()添加(“测试”);
返回cb;
}
}
}

我想在我的机器上运行您的代码,看看是否可以重现您描述的行为。为了做到这一点,我认为你应该提出你的问题,并发表一篇文章。添加了一个例子。我还注意到,我发现如果我将更新包装在Platform.runLater线程中,那么它似乎可以工作,但这似乎不是解决它的正确方法。不要将节点用作数据。。
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package javafxapplication;

import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;


public class JavaFXApplication extends Application {

    @Override
    public void start(Stage primaryStage) {

        TreeTableView treeTableView = new TreeTableView();

        treeTableView.getColumns().clear();

        TreeTableColumn<ProjectView, ComboBox> treeTableColumn = new TreeTableColumn<>("Dependencies");

        treeTableColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("comboBox"));

        treeTableColumn.setCellFactory(col -> {
            TreeTableCell<ProjectView, ComboBox> cell = new TreeTableCell<ProjectView, ComboBox>() {
                @Override
                public void updateItem(ComboBox item, boolean empty) {
                    super.updateItem(item, empty);
                    ComboBox newItem = new ComboBox();
                    newItem.getItems().add("Test");
                    newItem.setMinWidth(this.getWidth());
                    this.setGraphic(newItem);
                }

            };
            return cell;
        });

        List<ProjectView> projectList = new ArrayList<>();

        for (int i = 0; i < 25; i++) {
            projectList.add(new ProjectView());
        }

        treeTableView.getColumns().add(treeTableColumn);

        TreeItem treeRoot = new TreeItem();
        projectList.stream().filter((p) -> (p != null)).forEachOrdered((ProjectView p) -> {
            TreeItem project = new TreeItem(p);
            treeRoot.getChildren().add(project);
        });
        treeTableView.setShowRoot(false);
        treeTableView.setRoot(treeRoot);

        StackPane root = new StackPane();

        root.getChildren().add(treeTableView);
        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    public static class ProjectView {

        public ProjectView() {
        }

        public ComboBox getComboBox() {
            ComboBox cb = new ComboBox();
            cb.getItems().add("Test");
            return cb;
        }
    }

}