从ListView获取对象';单击列表项

从ListView获取对象';单击列表项,listview,javafx-8,Listview,Javafx 8,我有一个列表视图,其中填充了一个可观察列表 availableSymbolsTable.setItems(watch.GetAvailableSymbols()); 细胞工厂: availableSymbolsTable.setCellFactory(new Callback<ListView<Symbol>, ListCell<Symbol>>() { @Override public Li

我有一个列表视图,其中填充了一个可观察列表

availableSymbolsTable.setItems(watch.GetAvailableSymbols());
细胞工厂:

availableSymbolsTable.setCellFactory(new Callback<ListView<Symbol>, ListCell<Symbol>>()
        {

            @Override
            public ListCell<Symbol> call(ListView<Symbol> p)
            {
                final ListCell<Symbol> cell = new ListCell<Symbol>()
                {
                    @Override
                    protected void updateItem(Symbol t, boolean bln)
                    {
                        if (t != null)
                        {
                            setText(t.getSymbolName());
                        }

                        setOnMouseEntered(new EventHandler<MouseEvent>()
                        {
                            @Override
                            public void handle(MouseEvent event)
                            {
                                //This works
                                System.out.println("index: " + getIndex());
                            }
                        });

                        setOnMouseClicked(new EventHandler<MouseEvent>()
                        {
                            @Override
                            public void handle(MouseEvent event)
                            {
                                 //HERE getItem() always returns null
                                System.out.println( getItem().getSymbolName());         
                            }
                        });
                    }

                };
                return cell;}});}
availableSymbolsTable.setCellFactory(新回调()
{
@凌驾
公共ListCell调用(ListView p)
{
最终ListCell单元格=新ListCell()
{
@凌驾
受保护的void updateItem(符号t,布尔bln)
{
如果(t!=null)
{
setText(t.getSymbolName());
}
SetOnMouseCentered(新事件处理程序()
{
@凌驾
公共无效句柄(MouseeEvent事件)
{
//这很有效
System.out.println(“索引:+getIndex());
}
});
setOnMouseClicked(新事件处理程序()
{
@凌驾
公共无效句柄(MouseeEvent事件)
{
//这里getItem()总是返回null
System.out.println(getItem().getSymbolName());
}
});
}
};
返回单元格;}}});}
在MouseClicked事件处理程序中,getItem()方法始终返回null。如何获取关联的符号对象

编辑:
如果有帮助:我不知道预期的行为,但单击时,元素不会被选中。当我注释掉mouseClicked和mouseEntered处理程序时,会发生此事件。鼠标单击不起任何作用。

您不应该在
updateItem()
方法中设置侦听器,因为在呈现列表单元格时会多次调用它,所以您不希望不必要地重新设置它们。此外,在某些情况下,
updateItem()
项将为null,即单元格将为空,因此
getItem()
将返回null

试一试


您不应该在
updateItem()
方法中设置侦听器,因为在呈现列表单元格时会多次调用它,所以您不希望不必要地重新设置它们。此外,在某些情况下,
updateItem()
项将为null,即单元格将为空,因此
getItem()
将返回null

试一试


您在
updateItem(…)
方法中忽略了两件重要的事情:

  • 您必须调用
    super.updateItem(…)
    。这是必要的,以便正确维护
    属性的状态,以及处理诸如设置CSS伪类状态以进行选择和聚焦等事项
  • 必须处理单元格为空(或项为空)的情况,并清除该情况下的文本
  • 此外,正如Uluk Biy在回答中指出的,在
    updateItem(…)
    方法中设置处理程序不是一个好主意。此方法经常被调用,并且在创建单元格时只需设置一次处理程序

    所以你的细胞工厂应该是这样的

    availableSymbolsTable.setCellFactory( new Callback<ListView<Symbol>, ListCell<Symbol>>()
    {
        @Override
        public ListCell<Symbol> call( ListView<Symbol> p )
        {
            final ListCell<Symbol> cell = new ListCell<Symbol>()
            {
                @Override
                protected void updateItem( Symbol t, boolean empty )
                {
                    super.updateItem(t, empty);
                    if (empty) {
                        setText(null);
                    } else {
                        setText( t.getSymbolName() );
                    }
                }
            };
    
            cell.setOnMouseEntered( new EventHandler<MouseEvent>()
            {
                @Override
                public void handle( MouseEvent event )
                {
                    System.out.println( "index: " + cell.getIndex() );
                }
            } );
    
            cell.setOnMouseClicked( new EventHandler<MouseEvent>()
            {
                @Override
                public void handle( MouseEvent event )
                {
                    if ( cell.getItem() != null )
                    {
                        System.out.println( cell.getItem().getSymbolName() );
                    }
                }
            } );
    
            return cell;
        }
    } );
    
    availableSymbolsTable.setCellFactory(新回调()
    {
    @凌驾
    公共ListCell调用(ListView p)
    {
    最终ListCell单元格=新ListCell()
    {
    @凌驾
    受保护的void updateItem(符号t,布尔空)
    {
    super.updateItem(t,空);
    if(空){
    setText(空);
    }否则{
    setText(t.getSymbolName());
    }
    }
    };
    cell.setonmouseintered(新的EventHandler()
    {
    @凌驾
    公共无效句柄(MouseeEvent事件)
    {
    System.out.println(“index:+cell.getIndex());
    }
    } );
    cell.setOnMouseClicked(新的EventHandler()
    {
    @凌驾
    公共无效句柄(MouseeEvent事件)
    {
    if(cell.getItem()!=null)
    {
    System.out.println(cell.getItem().getSymbolName());
    }
    }
    } );
    返回单元;
    }
    } );
    
    另外,由于您使用的是JavaFX8,因此可以通过使用Lambda表达式大大简化此代码:

    availableSymbolsTable.setCellFactory(lv -> {
        ListCell<Symbol> cell = new ListCell<Symbol>() {
            @Override
            protected void updateItem(Symbol t, boolean empty) {
                super.updateItem(t, empty);
                if (empty) {
                    setText(null);
                } else {
                    setText(t.getSymbolName());
                }
            }
        };
    
        cell.setOnMouseEntered(e -> {
            System.out.println("Index: "+cell.getIndex());
        });
    
        cell.setOnMouseClicked(e -> {
            if (cell.getItem() != null) {
                System.out.println(cell.getItem().getSymbolName());
            }
        });
    
        return cell ;
    }
    
    可用SYMBOLSTABLE.setCellFactory(lv->{
    ListCell=新ListCell(){
    @凌驾
    受保护的void updateItem(符号t,布尔空){
    super.updateItem(t,空);
    if(空){
    setText(空);
    }否则{
    setText(t.getSymbolName());
    }
    }
    };
    cell.SetonMouseCentered(e->{
    System.out.println(“Index:+cell.getIndex());
    });
    cell.setOnMouseClicked(e->{
    if(cell.getItem()!=null){
    System.out.println(cell.getItem().getSymbolName());
    }
    });
    返回单元;
    }
    
    您在
    updateItem(…)
    方法中忽略了两件重要的事情:

  • 您必须调用
    super.updateItem(…)
    。这是正确维护
    属性的状态,以及处理设置CSS伪类状态以进行选择和聚焦等操作所必需的
  • 必须处理单元格为空(或项为空)的情况,并清除该情况下的文本
  • 此外,正如Uluk Biy在回答中指出的,在
    updateItem(…)
    方法中设置处理程序不是一个好主意。此方法经常调用,并且在创建单元格时只需设置一次处理程序

    所以
    availableSymbolsTable.setCellFactory( new Callback<ListView<Symbol>, ListCell<Symbol>>()
    {
        @Override
        public ListCell<Symbol> call( ListView<Symbol> p )
        {
            final ListCell<Symbol> cell = new ListCell<Symbol>()
            {
                @Override
                protected void updateItem( Symbol t, boolean empty )
                {
                    super.updateItem(t, empty);
                    if (empty) {
                        setText(null);
                    } else {
                        setText( t.getSymbolName() );
                    }
                }
            };
    
            cell.setOnMouseEntered( new EventHandler<MouseEvent>()
            {
                @Override
                public void handle( MouseEvent event )
                {
                    System.out.println( "index: " + cell.getIndex() );
                }
            } );
    
            cell.setOnMouseClicked( new EventHandler<MouseEvent>()
            {
                @Override
                public void handle( MouseEvent event )
                {
                    if ( cell.getItem() != null )
                    {
                        System.out.println( cell.getItem().getSymbolName() );
                    }
                }
            } );
    
            return cell;
        }
    } );
    
    availableSymbolsTable.setCellFactory(lv -> {
        ListCell<Symbol> cell = new ListCell<Symbol>() {
            @Override
            protected void updateItem(Symbol t, boolean empty) {
                super.updateItem(t, empty);
                if (empty) {
                    setText(null);
                } else {
                    setText(t.getSymbolName());
                }
            }
        };
    
        cell.setOnMouseEntered(e -> {
            System.out.println("Index: "+cell.getIndex());
        });
    
        cell.setOnMouseClicked(e -> {
            if (cell.getItem() != null) {
                System.out.println(cell.getItem().getSymbolName());
            }
        });
    
        return cell ;
    }