我有一个填充了可观察列表的列表视图
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;}});}
在MouseClicked事件处理程序中,getItem()方法始终返回null。如何获取关联的Symbol对象?
编辑: 如果它有帮助:我不知道预期的行为,但点击时,元素不会被选中。当我注释掉mouseClicked和mouseEntered处理程序时会发生这种情况。鼠标单击不执行任何操作。
答案 0 :(得分:3)
你不应该用updateItem()
方法设置监听器,因为在渲染列表单元格时会多次调用它,你不想再次不必要地设置它们。此外,在updateItem()
item
的某些情况下,getItem()
将为空,即单元格将为空,因此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 )
{
super.updateItem(t, empty);
if ( t != null )
{
setText( t.getSymbolName() );
}
else
{
setText( null );
}
}
};
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;
}
} );
将返回null。
尝试
selectedItemProperty
另请注意,用户可以使用键盘选择列表项,如果您还想处理它们,则更适合观察availableSymbolsTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Symbol>()
{
@Override
public void changed( ObservableValue<? extends Symbol> observable, Symbol oldValue, Symbol newValue )
{
System.out.println( "newValue = " + newValue );
}
});
:
function test(val) {
var x = Math.floor(val);
return (val - x) > 0.5 ? Math.ceil(val) : (x + 0.5);
}
答案 1 :(得分:2)
您在updateItem(...)
方法中省略了两件重要的事情:
super.updateItem(...)
。这是为了正确维护item
和empty
属性的状态,以及处理诸如为选择和焦点设置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;
}
} );
顺便说一下,由于您使用的是JavaFX 8,因此可以使用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 ;
}