如何在JavaFX可编辑的TreeTableView中提供货币LongProperty的编辑?

如何解决如何在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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-