如何在单元格';JavaFx中的updateItem方法?
我希望有一个带有自定义如何在单元格';JavaFx中的updateItem方法?,javafx,tableview,javafx-8,tablecell,Javafx,Tableview,Javafx 8,Tablecell,我希望有一个带有自定义图形的TableCell,该图形根据值的变化进行动画制作,其中动画类型取决于变化的性质,因此我需要知道前一个值以与当前值进行比较 以下是典型的自定义表格单元格(Kotlin代码): 我只能想到一个丑陋的解决方法,所以我想知道是否有一些惯用的方法来获取旧的单元格值 以下是一个示例应用程序: 导入javafx.application.application 导入javafx.beans.property.SimpleDoubleProperty 导入javafx.collec
图形的TableCell
,该图形根据值的变化进行动画制作,其中动画类型取决于变化的性质,因此我需要知道前一个值以与当前值进行比较
以下是典型的自定义表格单元格(Kotlin代码):
我只能想到一个丑陋的解决方法,所以我想知道是否有一些惯用的方法来获取旧的单元格值
以下是一个示例应用程序:
导入javafx.application.application
导入javafx.beans.property.SimpleDoubleProperty
导入javafx.collections.FXCollections
导入javafx.scene.scene
导入javafx.scene.control*
导入javafx.scene.control.cell.PropertyValueFactory
导入javafx.stage.stage
导入kotlinx.coroutines.experimental.delay
导入kotlinx.coroutines.experimental.launch
导入tornadofx*
福班{
val barProperty=SimpleDoubleProperty()
变量条:双
get()=barProperty.get()
设置(值)=barProperty.set(值)
}
类FooApp:Application(){
覆盖乐趣开始(初级阶段:阶段){
val foos=FXCollections.observearraylist(
Foo().apply{bar=42.0}
)
val表格=表格视图(foos)
val barColumn=TableColumn(“条形”)
barColumn.cellValueFactory=PropertyValueFactory(“bar”)
barColumn.setCellFactory{
FooTableCell{“%.2f”.format(it)}
}
table.columns.add(barColumn)
val场景=场景(表,400.0,200.0)
primaryStage.scene=场景
primaryStage.title=“表格单元格”
primaryStage.show()
发射{
while(isActive){
延迟(500)
val oldFoo=foos[0]
//用新实例替换旧的Foo实例,
//更新'bar'字段的值:
foos[0]=Foo().apply{
bar=oldFoo.bar-1.0+Math.random()*2.0
}
//因为对字段的更改不能被可观察列表检测到
//因此不会传播到表中。这不会导致
//一个明显的变化:
//foos[0]。bar=foos[0]。bar-1.0+Math.random()*2.0
}
}
}
}
类FooTableCell(私有val格式:(T)->字符串):TableCell(){
初始化{
contentDisplay=contentDisplay.GRAPHIC\u仅限
itemProperty().addListener(ChangeListener{obs,oldItem,newItem->
if(newItem!=null&&oldItem!=null&&newItem!=oldItem){
//这从来都不是真的。
println(!!!旧:$oldItem,新:$newItem)
}否则{
println(“更改侦听器:\nOld:$oldItem,New:$newItem\n”)
}
})
}
重写fun updateItem(项:T?,空:布尔值){
val oldItem=this.item
super.updateItem(项,空)
if(item!=null&&oldItem!=null&&item!=oldItem){
//这从来都不是真的。
println(!!!旧:$oldItem,新:$item)
}否则{
println(“updateItem:\nOld:$oldItem,New:$item\n”)
}
if(空| |项==null){
图形=空
text=null
}else if(tableRow!=null){
val cell=此
图形=标签()。应用{
textProperty().bindproduction(cell.textProperty())
}
文本=格式(项目)
}
}
}
趣味主线(args:Array){
launch(FooApp::class.java,*args)
}
通过updateItem()
方法的默认实现更改项的实际值,因此只需在调用默认实现之前获取值:
public class MyTableCell<S,T> extends TableCell<S,T> {
@Override
protected void updateItem(T item, boolean empty) {
T oldItem = getItem();
super.updateItem(item, empty) ;
// ...
}
}
以下是一个SSCCE,演示了这两种技术:
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class TableCellWithChange extends Application {
public static class ChangeAwareCell<S,T> extends TableCell<S,T> {
public ChangeAwareCell() {
itemProperty().addListener((obs, oldItem, newItem) -> {
System.out.printf("In listener, value for %s changed from %s to %s%n", getTableRow().getItem(), oldItem, newItem);
});
}
@Override
protected void updateItem(T item, boolean empty) {
T oldItem = getItem();
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
setText(item.toString());
System.out.printf("Change in %s from %s to %s %n", getTableView().getItems().get(getIndex()), oldItem, item);
}
}
}
@Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
TableColumn<Item, String> itemCol = column("Item", Item::nameProperty);
table.getColumns().add(itemCol);
TableColumn<Item, Number> valueCol = column("Value", Item:: valueProperty);
table.getColumns().add(valueCol);
valueCol.setCellFactory(tc -> new ChangeAwareCell<>());
TableColumn<Item, Void> changeCol = new TableColumn<>();
changeCol.setCellFactory(tc -> new TableCell<>() {
private Button incButton = new Button("^");
private Button decButton = new Button("v");
private HBox graphic = new HBox(2, incButton, decButton);
{
incButton.setOnAction(e -> {
Item item = getTableRow().getItem();
item.setValue(item.getValue()+1);
});
decButton.setOnAction(e -> {
Item item = getTableRow().getItem();
item.setValue(item.getValue()-1);
});
}
@Override
protected void updateItem(Void item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
setGraphic(graphic);
}
}
});
table.getColumns().add(changeCol);
Random rng = new Random();
for (int i = 1 ; i <= 20 ; i++) {
table.getItems().add(new Item("Item "+i, rng.nextInt(100)));
}
Scene scene = new Scene(table);
primaryStage.setScene(scene);
primaryStage.show();
}
private <S,T> TableColumn<S,T> column(String text, Function<S, ObservableValue<T>> property) {
TableColumn<S,T> col = new TableColumn<>(text);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
col.setPrefWidth(150);
return col ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
setName(name);
setValue(value);
}
@Override
public String toString() {
return getName();
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final IntegerProperty valueProperty() {
return this.value;
}
public final int getValue() {
return this.valueProperty().get();
}
public final void setValue(final int value) {
this.valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}
import java.util.Random;
导入java.util.function.function;
导入javafx.application.application;
导入javafx.beans.property.IntegerProperty;
导入javafx.beans.property.SimpleIntegerProperty;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.beans.value.observeValue;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.TableCell;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TableView;
导入javafx.scene.layout.HBox;
导入javafx.stage.stage;
公共类TableCellWithChange扩展了应用程序{
公共静态类ChangeAwareCell扩展TableCell{
公共变更通知(){
itemProperty().addListener((obs、oldItem、newItem)->{
System.out.printf(“在侦听器中,%s的值从%s更改为%s%n”,getTableRow().getItem(),oldItem,newItem);
});
}
@凌驾
受保护的void updateItem(T项,布尔值为空){
T oldItem=getItem();
super.updateItem(项,空);
if(空){
setText(空);
}否则{
setText(item.toString());
System.out.printf(“将%s从%s更改为%s%n”,getTableView().getItems().get(getIndex()),oldItem,item);
}
}
}
@凌驾
公共无效开始(阶段primaryStage){
TableView table=新TableView();
TableColumn itemCol=列(“项”,项::名称属性);
table.getColumns().add(itemCol);
TableColumn valueCol=列(“值”,项::valueProperty);
table.getColumns().add(valueCol);
valueCol.setCellFactory(tc->new ChangeAwareCell());
TableColumn changeCol=新的TableColumn();
changeCol.setCellFactory(tc->new TableCell(){
私有按钮incButton=新按钮(“^”);
专用按钮decButton=新按钮(“v”);
专用HBox图形=新HBox(2,递增按钮,递减按钮);
{
因克巴托
import javafx.application.Application
import javafx.beans.property.SimpleDoubleProperty
import javafx.collections.FXCollections
import javafx.scene.Scene
import javafx.scene.control.*
import javafx.scene.control.cell.PropertyValueFactory
import javafx.stage.Stage
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import tornadofx.*
class Foo {
val barProperty = SimpleDoubleProperty()
var bar: Double
get() = barProperty.get()
set(value) = barProperty.set(value)
}
class FooApp: Application() {
override fun start(primaryStage: Stage) {
val foos = FXCollections.observableArrayList(
Foo().apply { bar = 42.0 }
)
val table = TableView<Foo>(foos)
val barColumn = TableColumn<Foo, Double>("Bar")
barColumn.cellValueFactory = PropertyValueFactory<Foo, Double>("bar")
barColumn.setCellFactory {
FooTableCell<Foo, Double> { "%.2f".format(it) }
}
table.columns.add(barColumn)
val scene = Scene(table, 400.0, 200.0)
primaryStage.scene = scene
primaryStage.title = "Table Cell"
primaryStage.show()
launch {
while (isActive) {
delay(500)
val oldFoo = foos[0]
// Replacing the old Foo instance with a new one,
// updating the value of the `bar` field:
foos[0] = Foo().apply {
bar = oldFoo.bar - 1.0 + Math.random() * 2.0
}
// because a change to a field cannot be detected by an observable list
// and so does not propagates to the table. This won't result in
// a visible change:
// foos[0].bar = foos[0].bar - 1.0 + Math.random() * 2.0
}
}
}
}
class FooTableCell<S, T>(private val format: (T) -> String) : TableCell<S, T>() {
init {
contentDisplay = ContentDisplay.GRAPHIC_ONLY
itemProperty().addListener(ChangeListener { obs, oldItem, newItem ->
if (newItem != null && oldItem != null && newItem != oldItem) {
// This is never true.
println("!!! Old: $oldItem, New: $newItem")
} else {
println("Change listener:\nOld: $oldItem, New: $newItem\n")
}
})
}
override fun updateItem(item: T?, empty: Boolean) {
val oldItem = this.item
super.updateItem(item, empty)
if (item != null && oldItem != null && item != oldItem) {
// This is never true.
println("!!! Old: $oldItem, New: $item")
} else {
println("updateItem:\nOld: $oldItem, New: $item\n")
}
if (empty || item == null) {
graphic = null
text = null
} else if (tableRow != null) {
val cell = this
graphic = Label().apply {
textProperty().bindBidirectional(cell.textProperty())
}
text = format(item)
}
}
}
fun main(args: Array<String>) {
Application.launch(FooApp::class.java, *args)
}
public class MyTableCell<S,T> extends TableCell<S,T> {
@Override
protected void updateItem(T item, boolean empty) {
T oldItem = getItem();
super.updateItem(item, empty) ;
// ...
}
}
public class MyTableCell<S,T> extends TableCell<S,T> {
public MyTableCell() {
itemProperty().addListener((obs, oldItem, newItem) -> {
// do animation here...
});
}
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
// other functionality here...
}
}
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class TableCellWithChange extends Application {
public static class ChangeAwareCell<S,T> extends TableCell<S,T> {
public ChangeAwareCell() {
itemProperty().addListener((obs, oldItem, newItem) -> {
System.out.printf("In listener, value for %s changed from %s to %s%n", getTableRow().getItem(), oldItem, newItem);
});
}
@Override
protected void updateItem(T item, boolean empty) {
T oldItem = getItem();
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
setText(item.toString());
System.out.printf("Change in %s from %s to %s %n", getTableView().getItems().get(getIndex()), oldItem, item);
}
}
}
@Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
TableColumn<Item, String> itemCol = column("Item", Item::nameProperty);
table.getColumns().add(itemCol);
TableColumn<Item, Number> valueCol = column("Value", Item:: valueProperty);
table.getColumns().add(valueCol);
valueCol.setCellFactory(tc -> new ChangeAwareCell<>());
TableColumn<Item, Void> changeCol = new TableColumn<>();
changeCol.setCellFactory(tc -> new TableCell<>() {
private Button incButton = new Button("^");
private Button decButton = new Button("v");
private HBox graphic = new HBox(2, incButton, decButton);
{
incButton.setOnAction(e -> {
Item item = getTableRow().getItem();
item.setValue(item.getValue()+1);
});
decButton.setOnAction(e -> {
Item item = getTableRow().getItem();
item.setValue(item.getValue()-1);
});
}
@Override
protected void updateItem(Void item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
setGraphic(graphic);
}
}
});
table.getColumns().add(changeCol);
Random rng = new Random();
for (int i = 1 ; i <= 20 ; i++) {
table.getItems().add(new Item("Item "+i, rng.nextInt(100)));
}
Scene scene = new Scene(table);
primaryStage.setScene(scene);
primaryStage.show();
}
private <S,T> TableColumn<S,T> column(String text, Function<S, ObservableValue<T>> property) {
TableColumn<S,T> col = new TableColumn<>(text);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
col.setPrefWidth(150);
return col ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
setName(name);
setValue(value);
}
@Override
public String toString() {
return getName();
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final IntegerProperty valueProperty() {
return this.value;
}
public final int getValue() {
return this.valueProperty().get();
}
public final void setValue(final int value) {
this.valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}
public static class ChangeAwareCell<S,T> extends TableCell<S,T> {
private Function<S, ObservableValue<T>> property ;
private ObservableValue<T> lastObservableValue ;
private ChangeListener<T> listener = (obs, oldValue, newValue) -> valueChanged(oldValue, newValue);
public ChangeAwareCell(Function<S, ObservableValue<T>> property) {
this.property = property ;
}
private void valueChanged(T oldValue, T newValue) {
System.out.printf("Value changed from %s to %s %n", oldValue, newValue);
}
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (lastObservableValue != null) {
lastObservableValue.removeListener(listener);
}
if (empty) {
setText(null);
} else {
lastObservableValue = property.apply(getTableRow().getItem());
lastObservableValue.addListener(listener);
setText(item.toString());
}
}
}
valueCol.setCellFactory(tc -> new ChangeAwareCell<>(Item::valueProperty));