英文:
How to provide Editing of a currency (LongProperty) within a JavaFX editable TreeTableView?
问题
以下是您提供的内容的中文翻译:
如何将BO货币(LongProperty)绑定到JavaFX可编辑的TreeTableView?使用数据绑定、TextFormatter和其他JavaFX工具。
对于普通的TextField,我找到了这个解决方案:使用TextField编辑货币
BO:
import java.util.Random;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;
public class SimpleBo {
// 一个简单的LongProperty,用于存储没有小数位的货币(56,81 €将变为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<>();
// 创建列(Long数据类型)。
TreeTableColumn<SimpleBo, Number> currencyColumn = new TreeTableColumn<>("货币");
// 绑定值
currencyColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("currencyLong"));
// 设置单元格工厂
currencyColumn.setCellFactory(param -> new TextFieldTreeTableCell<>());
// 将列添加到TreeTable中。
treeTableView.getColumns().add(currencyColumn);
SimpleBo firstBo = new SimpleBo();
SimpleBo secondBo = new SimpleBo();
SimpleBo thirdBo = new SimpleBo();
// 根项目
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);
// 为Tree设置根项目
treeTableView.setRoot(itemRoot);
treeTableView.setShowRoot(false);
treeTableView.setEditable(true);
return treeTableView;
}
}
目标是:
- 带有LongProperty的BO(以分为单位的货币值)
- 可编辑的TreeTable,按照用户已知的格式(可选的负号、千位分隔符、小数点分隔符、货币符号,不允许其他字符)
- BO和TreeTableColumn之间的双向绑定。
英文:
How do I bind a BO currency (LongProperty) to a Javafx editable TreeTableView? Using Databinding, TextFormatter and other javaFX Stuff.
For a normal TextField I found this solution: 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);
}
}
Application:
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;
}
}
The goal should be:
- Bo with a LongProperty (currency Value in cents)
- editable TreeTable, in the Users known format (optinal leading minus,
thousands separator, decimal separator, currency symbol, and no other
chars possible) - BiDirectionalBinding between Bo and TreeTableColumn.
答案1
得分: 0
以下是您要翻译的内容:
A Solution would by a "CurrencyTextFieldTreeTableCell" with a custom Design.
use the MyNumberStringConverter and Util Class ([from this Answer][1])
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>, TreeTableCell<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));
希望这对您有所帮助。
英文:
A Solution would by a "CurrencyTextFieldTreeTableCell" with a custom Design.
use the MyNumberStringConverter and Util Class (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>, TreeTableCell<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());
}
}
}
And change the setCellFactory to this:
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));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论