JavaFX学习之样例7

该代码是个可编辑的table。

import java.lang.reflect.*;
import java.util.Arrays;
import java.util.logging.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.beans.value.*;
import javafx.collections.*;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.Callback;

// click in the value column (a couple of times) to edit the value in the column.
// property editors are defined only for String and Boolean properties.
// change focus to something else to commit the edit.
public class TableViewPropertyEditor extends Application {
public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage stage) {
final Person aPerson = new Person("Fred", true);
final Label currentObjectValue = new Label(aPerson.toString());

TableView<NamedProperty> table = new TableView();
table.setEditable(true);

table.setItems(createNamedProperties(aPerson));

TableColumn<NamedProperty, String> nameCol = new TableColumn("Name");
nameCol.setCellValueFactory(new PropertyValueFactory<NamedProperty, String>(
"name"));

TableColumn<NamedProperty, Object> valueCol = new TableColumn("Value");
valueCol.setCellValueFactory(new PropertyValueFactory<NamedProperty, Object>(
"value"));
valueCol.setCellFactory(new Callback<TableColumn<NamedProperty, Object>, TableCell<NamedProperty, Object>>() {
@Override
public TableCell<NamedProperty, Object> call(
TableColumn<NamedProperty, Object> param) {
return new EditingCell();
}
});

//提交后更新pojo的值
valueCol.setOnEditCommit(new EventHandler<CellEditEvent<NamedProperty, Object>>() {
@Override
public void handle(CellEditEvent<NamedProperty, Object> t) {
int row = t.getTablePosition().getRow();
NamedProperty property = (NamedProperty) t.getTableView()
.getItems().get(row);
property.setValue(t.getNewValue());
currentObjectValue.setText(aPerson.toString());
}
});

table.getColumns().setAll(nameCol, valueCol);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

VBox layout = new VBox(10);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
layout.getChildren().setAll(currentObjectValue, table);
VBox.setVgrow(table, Priority.ALWAYS);

stage.setScene(new Scene(layout, 650, 600));
stage.show();
}

private ObservableList<NamedProperty> createNamedProperties(Object object) {
ObservableList<NamedProperty> properties = FXCollections
.observableArrayList();

for (Method method : object.getClass().getMethods()) {
String name = method.getName();
Class type = method.getReturnType();
if (type.getName().endsWith("Property")) {
try {
properties.add(new NamedProperty(name, (Property) method
.invoke(object)));
} catch (IllegalAccessException ex) {
Logger.getLogger(TableViewPropertyEditor.class.getName())
.log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(TableViewPropertyEditor.class.getName())
.log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(TableViewPropertyEditor.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}

return properties;
}

public class NamedProperty {
public NamedProperty(String name, Property value) {
nameProperty.set(name);
valueProperty = value;
}

private StringProperty nameProperty = new SimpleStringProperty();

public StringProperty nameProperty() {
return nameProperty;
}

public StringProperty getName() {
return nameProperty;
}

public void setName(String name) {
nameProperty.set(name);
}

private Property valueProperty;

public Property valueProperty() {
return valueProperty;
}

public Object getValue() {
return valueProperty.getValue();
}

public void setValue(Object value) {
valueProperty.setValue(value);
}
}

public class Person {
private final SimpleStringProperty firstName;
private final SimpleBooleanProperty married;

private Person(String firstName, Boolean isMarried) {
this.firstName = new SimpleStringProperty(firstName);
this.married = new SimpleBooleanProperty(isMarried);
}

public SimpleStringProperty firstNameProperty() {
return firstName;
}

public SimpleBooleanProperty marriedProperty() {
return married;
}

public String getFirstName() {
return firstName.get();
}

public void setFirstName(String fName) {
firstName.set(fName);
}

public Boolean getMarried() {
return married.get();
}

public void setMarried(Boolean isMarried) {
married.set(isMarried);
}

@Override
public String toString() {
return firstName.getValue() + ": " + married.getValue();
}
}

class EditingCell extends TableCell<NamedProperty, Object> {
private TextField textField;
private CheckBox checkBox;

public EditingCell() {
}

@Override
public void startEdit() { //开始编辑时,设置Graphic
if (!isEmpty()) {
super.startEdit();

if (getItem() instanceof Boolean) {
createCheckBox();
setText(null);
setGraphic(checkBox);
} else {
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
}

@Override
public void cancelEdit() { //结束编辑时,取消Graphic,设置text
super.cancelEdit();
System.out.println("cancel");
if (getItem() instanceof Boolean) {
setText(getItem().toString());
} else {
setText((String) getItem());
}
setGraphic(null);
}

@Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (getIndex() < 2) {
NamedProperty property = getTableView().getItems().get(
getIndex());
System.out.println("property=" + property.getValue());
System.out.println("item=" + getItem());
}
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (getItem() instanceof Boolean) { //为boolean就设置checkbox
if (checkBox != null) {
checkBox.setSelected(getBoolean());
}
setText(null);
setGraphic(checkBox);
} else { //设置textFiled
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
}
} else {
setText(getString());
setGraphic(null);
}
}
}

private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()
* 2);
textField.focusedProperty().addListener(//焦点失去时事件
new ChangeListener<Boolean>() {
@Override
public void changed(
ObservableValue<? extends Boolean> observable,
Boolean oldValue, Boolean newValue) {
if (!newValue) {
commitEdit(textField.getText()); //传递值
}
}
});
}

private void createCheckBox() {
checkBox = new CheckBox();
checkBox.setSelected(getBoolean());
checkBox.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
checkBox.focusedProperty().addListener(
new ChangeListener<Boolean>() {
@Override
public void changed(
ObservableValue<? extends Boolean> observable,
Boolean oldValue, Boolean newValue) {
if (!newValue) {
commitEdit(checkBox.isSelected());
}
}
});
}

private String getString() {
return getItem() == null ? "" : getItem().toString();
}

private Boolean getBoolean() {
return getItem() == null ? false : (Boolean) getItem();
}
}
}

一般使用自定义tableCell实现cell的多样化,重写updateItem,设置Graphic和Text内容。若要实现编辑功能则可以重写startEdit和cancelEdit方法,这样就有在需要编辑时,显示需要的node,取消时,只显示text。

需要注意的地方是需要实现column.setOnEditCommit方法,更新pojo的值。因为cell的值对应pojo里面的get的值,若你不更新pojo,则cell值不变。
举个例子:value column的cell即对应NamedProperty的getValue。在方法updateItem里面参数item和getItem()方法获取的对象均等于getValue()。
但是当我注释掉setOnEditCommit方法里面的property.setValue(t.getNewValue()); 然后编辑value值,按逻辑来说getValue()没变,页面显示的值应该不会变化, 但是结果却变了。我在updateItem方法里面输出item和NamedProperty的getValue,发现不一样了。这让我疑惑了。我在想不应该啊,这二个值应该一样的。我试着重新加载,也就是把窗口缩小,直到看不到那行记录,然后在拉大(table会重新加载)。再一输出,页面显示的值变回来了,二个打印一样了。Item和getItem()的值始终是来自pojo的get方法的。
在代码里面可以看到,通过监听checkBox和textField的焦点集中属性来传递修改后的值。
commitEdit(textField.getText());  //传递值

正是通过commitEdit方法,修改了item的值。然后在cancel里面获取item的值,此时是最新的(在这里发现为什么item和get方法的值不一样了)。其实也不需要这样做,直接在cancel里面textField.getText或checkBox.isSelected获取最新值。

理解不对的地方希望大家评论下

这里有个javafx学习的中文网站,我把内容都丢那上面去了。
http://www.jfxee.com/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值