在添加行时无法编辑TableView的单元格

时间:2019-03-13 13:15:36

标签: java javafx

我创建了一个表,我想在单击+按钮添加一行后立即开始编辑第一列。问题是,当我单击+按钮时,它不会将第一行置于编辑模式,而如果再次按下+按钮,它最终会将第一行置于编辑模式。我也想要它,以便一旦提交值,它就开始编辑下一列。

这是我的课程:

Cheque.java

package tester;

import java.math.BigDecimal;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;


public class Cheque
{

    private final SimpleStringProperty chequeNumber;
    private final SimpleObjectProperty<BigDecimal> chequeAmount;
    private final ObservableValue changeProperty;

    public Cheque()
    {
        this.chequeNumber = new SimpleStringProperty();
        this.chequeAmount = new SimpleObjectProperty<>();
        this.changeProperty = Bindings.concat(chequeNumber, chequeAmount);

    }

    public Cheque(String chequeNumber, BigDecimal amount)
    {
        this();
        this.chequeNumber.set(chequeNumber);
        this.chequeAmount.set(amount);
    }

    /**
     *
     * @return
     */
    public ObservableValue getChangedProperty()
    {
        return this.changeProperty;
    }

    /**
     * @return the chequeNumber
     */
    public SimpleStringProperty getChequeNumberProperty()
    {
        return chequeNumber;
    }

    /**
     * @return the chequeAmount
     */

    public SimpleObjectProperty<BigDecimal> getChequeAmountProperty()
    {
        return chequeAmount;
    }

    public String getChequeNumber()
    {
        return chequeNumber.get();
    }

    public void setChequeNumber(String newValue)
    {
        this.chequeNumber.set(newValue);
    }

    public BigDecimal getChequeAmount()
    {
        return chequeAmount.get();
    }

    public void setChequeAmount(BigDecimal newValue)
    {
        this.chequeAmount.set(newValue);
    }



}

ChequeTable.java

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package tester;

import java.math.BigDecimal;
import java.util.List;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;

public class ChequeTable
{

    private final TableView<Cheque> table;
    private final ObservableList<Cheque> data;
    private final SimpleObjectProperty<BigDecimal> chequeTotal;

    public ChequeTable()
    {

        this.table = new TableView<>();
        this.data = FXCollections.observableArrayList();
        this.chequeTotal = new SimpleObjectProperty<>();
        setUpTable();
    }



    public void clear()
    {
        this.data.clear();           
    }



    private void setUpTable()
    {

        this.table.setEditable(true);
        this.table.setItems(this.data);


        TableColumn<Cheque, String> numberCol = new TableColumn<Cheque, String>("Cheque #");
        numberCol.setCellFactory(column -> EditCell.createStringEditCell());
        numberCol.setCellValueFactory(features -> features.getValue().getChequeNumberProperty());
        numberCol.setMinWidth(100);

        TableColumn<Cheque, BigDecimal> chequeAmountCol = new TableColumn<Cheque, BigDecimal>("Total $");
        chequeAmountCol.setCellValueFactory(features -> features.getValue().getChequeAmountProperty());
        chequeAmountCol.setCellFactory(column -> EditCell.createMoneyEditCell());
        chequeAmountCol.setMinWidth(50);

        TableColumn<Cheque, Boolean> addCol = new TableColumn<Cheque, Boolean>();
        addCol.setGraphic(new Button("+"));
        addCol.setPrefWidth(45);
        addCol.setStyle("-fx-alignment: CENTER;");
        addCol.setSortable(false);
        Button addButton = (Button) addCol.getGraphic();
        addButton.setOnAction((ActionEvent e) ->
        {
            Cheque cheque = new Cheque("Cheque#", BigDecimal.ZERO.setScale(2));

            data.add(cheque);
            table.scrollTo(cheque);
            table.requestFocus();
            table.getSelectionModel().select(cheque);
            table.edit(table.getSelectionModel().getSelectedIndex(), numberCol);

        });
        this.table.getColumns().addAll(numberCol, chequeAmountCol, addCol);

    }

    public TableView getTableView()
    {
        return this.table;
    }




}

Tester.java

package tester;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class Tester extends Application
{

    @Override
    public void start(Stage primaryStage)
    {

        ChequeTable chequeTable = new ChequeTable();

        HBox root = new HBox();
        root.getChildren().addAll(chequeTable.getTableView());

        Scene scene = new Scene(root, 400, 300);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {

            launch(args);

    }

}

EditCell.java

package tester;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;
import javafx.event.Event;
import javafx.geometry.Pos;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyEvent;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.util.StringConverter;

public class EditCell<S, T> extends TableCell<S, T>
{

    // Text field for editing
    // TODO: allow this to be a plugable control.
    private final TextField textField = new TextField();

    // Converter for converting the text in the text field to the user type, and vice-versa:
    private final StringConverter<T> converter;
    private final TextAlignment alignment;

    /**
     *
     * @param converter
     * @param alignment
     */
    public EditCell(StringConverter<T> converter, TextAlignment alignment)
    {

        this.converter = converter;
        this.alignment = alignment;
        this.textField.setAlignment(getPosition(alignment));
        itemProperty().addListener((ObservableValue<? extends T> obx, T oldItem, T newItem) ->
        {

            if (newItem == null)
            {
                setText(null);

            } else
            {
                setText(converter.toString(newItem));
            }

        });

        setGraphic(textField);

        setContentDisplay(ContentDisplay.TEXT_ONLY);
        setAlignment(getPosition(alignment));

        textField.setOnAction(evt ->
        {
            commitEdit(this.converter.fromString(textField.getText()));
        });

        textField.focusedProperty().addListener((ObservableValue<? extends Boolean> obs, Boolean wasFocused, Boolean isNowFocused) ->
        {

            if (!isNowFocused)
            {
                commitEdit(this.converter.fromString(textField.getText()));
            }

        });

        textField.addEventFilter(KeyEvent.KEY_PRESSED, (KeyEvent event) ->
        {

            if (null != event.getCode())
            {
                switch (event.getCode())
                {
                    case ESCAPE:
                        textField.setText(converter.toString(getItem()));
                        cancelEdit();
                        event.consume();
                        break;
                    case UP:
                        getTableView().getSelectionModel().selectAboveCell();
                        event.consume();
                        break;
                    case DOWN:
                        getTableView().getSelectionModel().selectBelowCell();
                        event.consume();
                        break;
                    default:
                        break;
                }
            }

        });

    }

    /**
     *
     * Convenience converter that does nothing (converts Strings to themselves
     * and vice-versa...).
     *
     */
    public static final StringConverter<String> IDENTITY_CONVERTER = new StringConverter<String>()
    {

        @Override
        public String toString(String object)
        {
            return object;
        }

        @Override
        public String fromString(String string)
        {
            return string;
        }

    };

    /**
     *
     */
    public static final StringConverter<BigDecimal> BIG_DECIMAL_MONEY_CONVERTER = new StringConverter<BigDecimal>()
    {
        @Override
        public String toString(BigDecimal object)
        {
            if (object == null)
            {
                return null;
            } else
            {
                return object.toPlainString();
            }

        }

        @Override
        public BigDecimal fromString(String string)
        {
            BigDecimal test = new BigDecimal(string);

            test = test.setScale(2, RoundingMode.HALF_EVEN);

            return test;
        }
    };

    /**
     *
     * Convenience method for creating an EditCell for a String value.
     *
     * @param <S>
     * @return
     *
     */
    public static <S> EditCell<S, String> createStringEditCell()
    {
        return new EditCell<>(IDENTITY_CONVERTER, TextAlignment.LEFT);

    }

    /**
     *
     * @param <S>
     * @return
     */
    public static <S> EditCell<S, BigDecimal> createMoneyEditCell()
    {
        return new EditCell<>(BIG_DECIMAL_MONEY_CONVERTER, TextAlignment.RIGHT);
    }

    @Override
    public void updateItem(T item, boolean empty)
    {
        super.updateItem(item, empty);
        TableColumn tableCol = (TableColumn) getTableColumn();
        if (item != null && tableCol.getWidth() < new Text(item + "  ").getLayoutBounds().getWidth())
        {
            tooltipProperty().bind(Bindings.when(Bindings.or(emptyProperty(), itemProperty().isNull())).then((Tooltip) null).otherwise(new Tooltip(item.toString())));
        } else
        {
            tooltipProperty().bind(Bindings.when(Bindings.or(emptyProperty(), itemProperty().isNull())).then((Tooltip) null).otherwise((Tooltip) null));
        }
    }

    // set the text of the text field and display the graphic
    @Override
    public void startEdit()
    {

        super.startEdit();
        textField.setText(converter.toString(getItem()));
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        textField.requestFocus();

    }

    // revert to text display
    @Override
    public void cancelEdit()
    {

        super.cancelEdit();
        setContentDisplay(ContentDisplay.TEXT_ONLY);
        setAlignment(getPosition(alignment));
    }

    // commits the edit. Update property if possible and revert to text display
    @Override
    public void commitEdit(T item)
    {

        // This block is necessary to support commit on losing focus, because the baked-in mechanism
        // sets our editing state to false before we can intercept the loss of focus.
        // The default commitEdit(...) method simply bails if we are not editing...
        if (!isEditing() && !Objects.equals(item, getItem()))
        {

            TableView<S> table = getTableView();

            if (table != null)
            {

                TableColumn<S, T> column = getTableColumn();
                CellEditEvent<S, T> event = new CellEditEvent<>(table,
                        new TablePosition<>(table, getIndex(), column),
                        TableColumn.editCommitEvent(), item);
                Event.fireEvent(column, event);

            }

        }

        super.commitEdit(item);

        setContentDisplay(ContentDisplay.TEXT_ONLY);
        setAlignment(getPosition(alignment));
    }

    private static Pos getPosition(TextAlignment textAlignment)
    {

        switch (textAlignment)
        {
            case CENTER:
                return Pos.CENTER;
            case RIGHT:
                return Pos.CENTER_RIGHT;
            case LEFT:
                return Pos.CENTER_LEFT;
            default:
                return Pos.CENTER_LEFT;
        }
    }

}

0 个答案:

没有答案