如何解决如何在JavaFX可编辑的TreeTableView中提供货币LongProperty的编辑?
如何将BO货币(LongProperty)绑定到Javafx可编辑TreeTableView?使用数据绑定,TextFormatter和其他javaFX Stuff。
对于普通的TextField,我找到了以下解决方案:Editiing Currency with a TextField
Bo:
import java.util.Random;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;
public class SimpleBo {
//a simple LongProperty to store the currency without fractional digits (56,81 € would be 5681)
private LongProperty currencyLong = new SimpleLongProperty();
public SimpleBo() {
setCurrencyLong(new Random().nextLong());
}
public final LongProperty currencyLongProperty() {
return this.currencyLong;
}
public final long getCurrencyLong() {
return this.currencyLongProperty().get();
}
public final void setCurrencyLong(final long currencyLong) {
this.currencyLongProperty().set(currencyLong);
}
}
应用程序:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TextFieldTreeTableCell;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.stage.Stage;
public class BindingExample extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Scene scene = new Scene(createTreeTableView());
primaryStage.setScene(scene);
primaryStage.show();
}
private static TreeTableView<SimpleBo> createTreeTableView() {
TreeTableView<SimpleBo> treeTableView = new TreeTableView<>();
// Create column (Data type of Long).
TreeTableColumn<SimpleBo,Number> currencyColumn = new TreeTableColumn<>("Currency");
//Bind Values
currencyColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("currencyLong"));
//Set Cell Factory
currencyColumn.setCellFactory( param -> new TextFieldTreeTableCell<>());
// Add columns to TreeTable.
treeTableView.getColumns().add(currencyColumn);
SimpleBo firstBo = new SimpleBo();
SimpleBo secondBo = new SimpleBo();
SimpleBo thirdBo = new SimpleBo();
// Root Item
TreeItem<SimpleBo> itemRoot = new TreeItem<>(null);
TreeItem<SimpleBo> itemFirst = new TreeItem<>(firstBo);
TreeItem<SimpleBo> itemSecond = new TreeItem<>(secondBo);
TreeItem<SimpleBo> itemThird = new TreeItem<>(thirdBo);
itemRoot.getChildren().addAll(itemFirst,itemSecond,itemThird);
// Set root Item for Tree
treeTableView.setRoot(itemRoot);
treeTableView.setShowRoot(false);
treeTableView.setEditable(true);
return treeTableView;
}
}
目标应该是:
- 具有LongProperty(货币值,以美分计)的Bo
- 可编辑的TreeTable,采用用户已知的格式(最佳前导减号, 千位分隔符,十进制分隔符,货币符号以及其他 可能有字符)
- Bo和TreeTableColumn之间的双向绑定。
解决方法
解决方案将由具有自定义设计的“ CurrencyTextFieldTreeTableCell”完成。
使用MyNumberStringConverter和Util类(from this Answer)
CurrencyTextFieldTreeTableCell:
import javafx.geometry.Insets;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.util.Callback;
public class CurrencyTextFieldTreeTableCell extends TreeTableCell<SimpleBo,Number> {
public static Callback<TreeTableColumn<SimpleBo,Number>,TreeTableCell<SimpleBo,Number>> forTreeTableColumn() {
return forTreeTableColumn(new MyNumberStringConverter());
}
public static Callback<TreeTableColumn<SimpleBo,Number>> forTreeTableColumn(
final MyNumberStringConverter converter) {
return list -> new CurrencyTextFieldTreeTableCell(converter);
}
/***************************************************************************
* * Fields * *
**************************************************************************/
private HBox hBox = new HBox();
private Label currencyLabel = new Label("€");
private TextField textField = new TextField("" + 0l);
/***************************************************************************
* * Constructors * *
**************************************************************************/
public CurrencyTextFieldTreeTableCell() {
this(new MyNumberStringConverter());
}
private CurrencyTextFieldTreeTableCell(MyNumberStringConverter converter) {
this.getStyleClass().add("currency-text-field-tree-table-cell");
this.converter = converter;
setupTextField();
setupHBox();
setStyle("-fx-alignment: CENTER-RIGHT;");
}
/***************************************************************************
* * Properties * *
**************************************************************************/
private MyNumberStringConverter converter = new MyNumberStringConverter();
/** {@inheritDoc} */
@Override
public void startEdit() {
if (!isEditable() || !getTreeTableView().isEditable() || !getTableColumn().isEditable()) {
return;
}
super.startEdit();
if (isEditing()) {
this.setText(null);
if (hBox != null) {
this.setGraphic(hBox);
} else {
this.setGraphic(textField);
}
if (textField != null) {
textField.setText(getItemText());
textField.selectAll();
// requesting focus so that key input can immediately go into the
// TextField (see RT-28132)
textField.requestFocus();
}
}
}
/** {@inheritDoc} */
@Override
public void cancelEdit() {
super.cancelEdit();
this.setText(getItemText());
this.setGraphic(currencyLabel);
contentDisplayProperty().setValue(ContentDisplay.RIGHT);
}
/** {@inheritDoc} */
@Override
public void updateItem(Number item,boolean empty) {
super.updateItem(item,empty);
if (isEmpty()) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getItemText());
}
setText(null);
setGraphic(hBox);
} else {
setText(getItemText());
setGraphic(currencyLabel);
contentDisplayProperty().setValue(ContentDisplay.RIGHT);
}
}
}
private void setupTextField() {
TextFormatter<Number> textFormatter = new TextFormatter<>(Util.createFilter());
this.textField.setTextFormatter(textFormatter);
// Use onAction here rather than onKeyReleased (with check for Enter),// as otherwise we encounter RT-34685
this.textField.setOnAction(event -> {
if (converter == null) {
throw new IllegalStateException("Attempting to convert text input into Object,but provided "
+ "StringConverter is null. Be sure to set a StringConverter " + "in your cell factory.");
}
commitEdit(converter.fromString(textField.getText()).longValue());
event.consume();
});
this.textField.setOnKeyReleased(t -> {
if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
t.consume();
}
});
}
private void setupHBox() {
this.hBox.getChildren().add(this.textField);
this.hBox.getChildren().add(new Label(" €"));
this.hBox.setPadding(new Insets(this.hBox.getPadding().getTop() + 9.0D,this.hBox.getPadding().getRight(),this.hBox.getPadding().getBottom(),this.hBox.getPadding().getLeft()));
}
private String getItemText() {
if(converter == null) {
return getItem() == null ? "" : getItem().toString();
} else {
return converter.toString(getItem());
}
}
}
并将setCellFactory更改为此:
NumberFormat nFormat = NumberFormat.getInstance();
nFormat.setMinimumIntegerDigits(1);
nFormat.setMinimumFractionDigits(2);
nFormat.setMaximumFractionDigits(2);
MyNumberStringConverter numberStringConverter = new MyNumberStringConverter(nFormat);
// Set Cell Factory
currencyColumn.setCellFactory(
param -> CurrencyTextFieldTreeTableCell.forTreeTableColumn(numberStringConverter).call(param));
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。