JavaFX中的“会计”样式表单元格

时间:2018-01-31 22:28:55

标签: java javafx alignment tablecell

有没有办法在JavaFX表中创建“会计”样式单元格? 通过计算我的意思是让美元符号左对齐并且值在单元格中右对齐。以下是Excel中的内容:

Excel Accounting Cell Format

这是我到目前为止所尝试的内容:

public class PriceTableCell<S> extends TableCell<S, Long>
{
    public PriceTableCell()
    {
        final Label label = new Label("$");
        this.setAlignment(Pos.CENTER_RIGHT);
        this.setContentDisplay(ContentDisplay.LEFT);
        this.setGraphic(label);
    }

    @Override
    protected void updateItem(Long item, boolean empty)
    {
        if (item == null || empty)
        {
            this.setText(null);
            return;
        }

        this.setText(String.format(Locale.ENGLISH, "%,d.%02d", item / 100, Math.abs(item % 100)));
    }
}

不幸的是,我找不到为图形和文本设置单独对齐的方法。 JavaFX将如上所示呈现如下:

JavaFX attempt

1 个答案:

答案 0 :(得分:3)

AnchorPane中使用两个标签应该有效。

(更新:根据@kleopatra的建议,我在此解决方案中加入了DecimalFormat,它将(至少部分地)本地化货币符号,以及小数位数等这将假设货币符号显示在货币值的左侧,这对所有货币都不一定是正确的,但无论如何,该假设在某种程度上隐含在问题中。)

public class PriceTableCell<S> extends TableCell<S, Long> {

    private final AnchorPane pane ;
    private final Label valueLabel ;
    // locale-aware currency format to use for formatting
    private DecimalFormat format;

    public PriceTableCell() {
        // grab an instance
        format = (DecimalFormat) NumberFormat.getCurrencyInstance();
        //get the currency symbol
        String symbol = format.getCurrency().getSymbol();
        // replace the currency symbol with an empty string
        DecimalFormatSymbols symbols = format.getDecimalFormatSymbols();
        symbols.setCurrencySymbol("");
        format.setDecimalFormatSymbols(symbols);

        Label currencySignLabel = new Label(symbol);
        valueLabel = new Label();
        pane = new AnchorPane(currencySignLabel, valueLabel);
        AnchorPane.setLeftAnchor(currencySignLabel, 0.0);
        AnchorPane.setRightAnchor(valueLabel, 0.0);
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    }

    @Override
    protected void updateItem(Long price, boolean empty) {
        super.updateItem(price, empty);
        if (empty) {
            setGraphic(null);
        } else {
            // manual formatting 
            //String text = String.format("%,d.%02d", price / 100, Math.abs(price % 100));
            valueLabel.setText(format.format(price));
            setGraphic(pane);
        }
    }
}

这是一个SSCCE:

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Random;
import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class TableViewWithAccountingStyleCell extends Application {

    public static class PriceTableCell<S> extends TableCell<S, Long> {

        private final AnchorPane pane ;
        private final Label valueLabel ;
        // locale-aware currency format to use for formatting
        private DecimalFormat format;

        public PriceTableCell() {
            // grab an instance
            format = (DecimalFormat) NumberFormat.getCurrencyInstance();
            //get the currency symbol
            String symbol = format.getCurrency().getSymbol();
            // replace the currency symbol with an empty string
            DecimalFormatSymbols symbols = format.getDecimalFormatSymbols();
            symbols.setCurrencySymbol("");
            format.setDecimalFormatSymbols(symbols);

            Label currencySignLabel = new Label(symbol);
            valueLabel = new Label();
            pane = new AnchorPane(currencySignLabel, valueLabel);
            AnchorPane.setLeftAnchor(currencySignLabel, 0.0);
            AnchorPane.setRightAnchor(valueLabel, 0.0);
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        }

        @Override
        protected void updateItem(Long price, boolean empty) {
            super.updateItem(price, empty);
            if (empty) {
                setGraphic(null);
            } else {
                // manual formatting 
                //String text = String.format("%,d.%02d", price / 100, Math.abs(price % 100));
                valueLabel.setText(format.format(price));
                setGraphic(pane);
            }
        }
    }

    public static class Item {
        private final StringProperty name = new SimpleStringProperty();
        private final LongProperty price = new SimpleLongProperty();

        public Item(String name, long price) {
            setName(name);
            setPrice(price);
        }

        public StringProperty nameProperty() {
            return name ;
        }

        public final String getName() {
            return nameProperty().get();
        }

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

        public LongProperty priceProperty() {
            return price ;
        }

        public final long getPrice() {
            return priceProperty().get();
        }

        public final void setPrice(long price) {
            priceProperty().set(price);
        }
    }

    @Override
    public void start(Stage primaryStage) {
        TableView<Item> table = new TableView<>();
        table.getColumns().add(column("Item", Item::nameProperty));
        TableColumn<Item, Long> priceColumn = column("Price", item -> item.priceProperty().asObject());
        priceColumn.setPrefWidth(300);

        priceColumn.setCellFactory(tc -> new PriceTableCell<>());

        table.getColumns().add(priceColumn);


        Random rng = new Random();
        for (int i = 1 ; i <= 20 ; i++) {
            table.getItems().add(new Item("Item "+i, rng.nextInt(1_000_000)));
        }

        Scene scene = new Scene(table);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private <S,T> TableColumn<S,T> column(String name, Function<S, ObservableValue<T>> property) {
        TableColumn<S,T> column = new TableColumn<>(name);
        column.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
        return column ;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

产生

enter image description here