代码之家  ›  专栏  ›  技术社区  ›  Mertcan Özdemir

JavaFX combobox正在调用listcell。无限更新项

  •  0
  • Mertcan Özdemir  · 技术社区  · 6 年前

    我正在尝试制作一个包含大量项目(超过10000个)的组合框。它初始化没有问题。但当我点击它时,它就冻结了。为了进行调试,我创建了自己的listCell并使用updateitem函数。当我点击时,它无限地调用updateitem。它不应该只更新可见的项目吗?以下是控制器示例:

       package sample;
    
    import javafx.fxml.FXML;
    import javafx.scene.control.ComboBox;
    import javafx.scene.control.Label;
    import javafx.scene.control.ListCell;
    
    
    public class Controller {
        @FXML
        ComboBox comboBox1;
    
        public final class ExampleCell<T> extends ListCell<T> {
    
            Label myLabel;
    
            @Override
            protected void updateItem(T item, boolean empty) {
                super.updateItem(item,empty);
                System.out.println("update");
                if (empty) {
                    setGraphic(null);
                } else {
                    if(myLabel==null){
                        myLabel=new Label((String)item);
    
                    }else{
                        myLabel.setText((String)item);}
                    setGraphic(myLabel);
                }
            }
        }
        public void initialize(){
    
        for(int i =0;i<10000;i++){
            comboBox1.getItems().add("example");
        }
        comboBox1.setCellFactory(param -> new ExampleCell<>());
       }
    }
    

    和我的fxml

    <?import javafx.scene.layout.GridPane?>
    
    <?import javafx.scene.control.ComboBox?>
    <GridPane fx:controller="sample.Controller"
              prefWidth="500"
              prefHeight="500"
              xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
        <ComboBox
                fx:id="comboBox1"
        />
    </GridPane>
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   kleopatra    6 年前

    原因确实是测量所有单元格的pref宽度,因为(不是公开的!)记录在ComboBoxListViewSkin中:

    // By default we measure the width of all cells in the ListView. If this
    // is too burdensome, the developer may set a property in the ComboBox
    // properties map with this key to specify the number of rows to measure.
    // This may one day become a property on the ComboBox itself.
    private static final String COMBO_BOX_ROWS_TO_MEASURE_WIDTH_KEY = "comboBoxRowsToMeasureWidth";
    

    解决方法是限制应该测量的行数-没有保证,因为没有公共文档根本就没有规范:

    comboBox1.getProperties().put("comboBoxRowsToMeasureWidth", 10);
    

    最初仍然大量调用updateItem,这至少是测量(填充和释放)期间给定限制的两倍,加上一次用于设置实际值。