编辑TableColumn时出现ClassCastException

时间:2016-03-28 19:30:45

标签: java javafx tableview javafx-8

我想设置可编辑以下代码的quantityColumn

public class ControladorView implements Initializable {

    @FXML private MenuItem mNew, mOpen, mSave, mPrint;

    @FXML
    private MenuButton mCategory;

    @FXML private Button bAccept, bCancel, bAdd, bRemove, bClear;

    @FXML private TableView tableViewItem;
    @FXML private TableColumn<Product, String> nameItemColumn;
    @FXML private TableColumn<Product, Double> priceColumn;
    @FXML private TableColumn<Product, Integer> availableColumn;

    private ObservableList<Product> itemData;

    @FXML private TableView tableViewBudget;
    @FXML private TableColumn<Product, String> nameBudgetColumn;
    @FXML private TableColumn<Product, Double> outTaxColumn;
    @FXML private TableColumn<Product, Double> inTaxColumn;
    @FXML private TableColumn<Product, Integer> quantityColumn;

    private ObservableList<Product> budgetData;

    @FXML private TextField tFName, tFMin, tFMax;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        //Items Table
        nameItemColumn.setCellValueFactory(
            new PropertyValueFactory<>("description"));
        priceColumn.setCellValueFactory(
            new PropertyValueFactory<>("price"));
        availableColumn.setCellValueFactory(
            new PropertyValueFactory<>("stock"));

        //Se utiliza para Añadir
        itemData = FXCollections.observableArrayList();

        //Budget Table
        nameBudgetColumn.setCellValueFactory(
            new PropertyValueFactory<>("description"));
        inTaxColumn.setCellValueFactory(
            new PropertyValueFactory<>("price"));
        outTaxColumn.setCellValueFactory(cellData ->
            new SimpleDoubleProperty(cellData.getValue().getPrice() * 0.79 ).asObject());
        nameBudgetColumn.setCellFactory(tc -> new TextFieldTableCell<>());

        //Se utiliza para Eliminar y Limpiar
        budgetData = FXCollections.observableArrayList();
        tableViewBudget.setItems(budgetData);

        //Bindings Filter
        final BooleanBinding noFiltOp = Bindings.equal(mCategory.textProperty(), "Categoría").or(
                                        Bindings.equal(mCategory.textProperty(), "Categoría").and(
                                        Bindings.isEmpty(tFMin.textProperty())).and(
                                        Bindings.isEmpty(tFMax.textProperty()))).or(
                                        Bindings.equal(mCategory.textProperty(), "Categoría").and(
                                        Bindings.isEmpty(tFName.textProperty()))).or(
                                        Bindings.equal(mCategory.textProperty(), "Categoría").and(
                                        Bindings.isEmpty(tFName.textProperty())).and(
                                        Bindings.isEmpty(tFMin.textProperty())).and(
                                        Bindings.isEmpty(tFMax.textProperty())));

        final BooleanBinding noCancel = Bindings.isEmpty(tFName.textProperty()).and(
                                        Bindings.equal(mCategory.textProperty(), "Categoría")).and(
                                        Bindings.isEmpty(tFMin.textProperty())).and(
                                        Bindings.isEmpty(tFMax.textProperty()));

        //Bindings Item
        final BooleanBinding noItemSelectedI = Bindings.isNull(
            tableViewItem.getSelectionModel().selectedItemProperty());

        //Bindings Budget
        final BooleanBinding noItemSelectedB = Bindings.isNull(
            tableViewBudget.getSelectionModel().selectedItemProperty());
        final BooleanBinding emptyBudget = Bindings.isEmpty(tableViewBudget.getItems());

        //Disable buttons
        bAccept.disableProperty().bind(noFiltOp);
        bCancel.disableProperty().bind(noCancel);
        bAdd.disableProperty().bind(noItemSelectedI);
        bRemove.disableProperty().bind(noItemSelectedB);
        bClear.disableProperty().bind(emptyBudget);
    }

    @FXML
    private void onSelect(ActionEvent event) {
        mCategory.setText(((MenuItem) event.getSource()).getText());
    }

    @FXML
    private void onAccept(ActionEvent event) {
        Category op = Product.Category.POWER_SUPPLY;
        switch(mCategory.getText()) {
            case "Placas Base": op = Product.Category.MOTHERBOARD; break;
            case "Procesadores": op = Product.Category.CPU; break;
            case "Memorias RAM": op = Product.Category.RAM; break;
            case "Tarjetas gráficas": op = Product.Category.GPU; break;
            case "HDD": op = Product.Category.HDD; break;
            case "SSD": op = Product.Category.HDD_SSD; break;
            case "Torres": op = Product.Category.CASE; break;
            case "Teclados": op = Product.Category.KEYBOARD; break;
            case "Ratones": op = Product.Category.MOUSE; break;
            case "Monitores": op = Product.Category.SCREEN; break;
            case "Altavoces": op = Product.Category.SPEAKER; break;
            case "Multilectores": op = Product.Category.MULTIREADER; break;
            case "Grabadoras": op = Product.Category.DVD_WRITER; break;
            case "Ventiladores": op = Product.Category.FAN; break;
        }

        //Condiciones (true) para metodos Database
        final boolean cat = !mCategory.getText().equals("Categoría"),
                      des = !tFName.getText().isEmpty(),
                      min = !tFMin.getText().isEmpty(),
                      max = !tFMax.getText().isEmpty();

        if(cat && des && min && max)
            tableViewItem.getItems().setAll(
                Database.getProductByCategoryDescriptionAndPrice(
                    op, tFName.getText(), Double.parseDouble(tFMin.getText()),
                    Double.parseDouble(tFMax.getText()), true));
        else if(cat && min && max)
            tableViewItem.getItems().setAll(
                Database.getProductByCategoryAndPrice(
                    op, Double.parseDouble(tFMin.getText()),
                    Double.parseDouble(tFMax.getText()), true));
        else if(cat && des)
            tableViewItem.getItems().setAll(
                Database.getProductByCategoryAndDescription(
                    op, tFName.getText(), true));
        else tableViewItem.getItems().setAll(Database.getProductByCategory(op));
    }

    @FXML
    private void onCancel(ActionEvent event) {
        tFName.clear();
        mCategory.setText("Categoría");
        tFMin.clear();
        tFMax.clear();
        tableViewItem.getItems().clear();
    }

    @FXML
    private void onAdd(ActionEvent event) {
        Product prod =
            ((Product) tableViewItem.getSelectionModel().selectedItemProperty().getValue());     
        if(!budgetData.isEmpty()) {
            Product[] elArray = new Product[budgetData.size()];
            elArray = budgetData.toArray(elArray);
            Category cat = prod.getCategory();
            try {
                int i = 0;
                while(!elArray[i].getCategory().equals(cat)) i++;
            } catch(ArrayIndexOutOfBoundsException e) {
                budgetData.add(prod);
            }
        } else budgetData.add(prod);
    }

    @FXML
    private void onRemove(ActionEvent event) {
        budgetData.remove(tableViewBudget.getSelectionModel().getSelectedIndex());
    }

    @FXML
    private void onClear(ActionEvent event) {
        tableViewBudget.getItems().clear();
    }
}

我尝试了很多事情,但总是在ClassCastExceptionProduct之间抛出ProductoProduct无法投放到Producto) 。所以我决定发布原始的控制器类。

产品类别:

public class Product {
    public enum Category {
        SPEAKER, HDD, HDD_SSD, POWER_SUPPLY, DVD_WRITER, RAM, SCREEN,
        MULTIREADER, MOTHERBOARD, CPU, MOUSE, GPU, KEYBOARD, CASE, FAN
    }

    public Product(String description, double price, int stock, Category category) {
        this.description = description;
        this.price = price;
        this.stock = stock;
        this.category = category;
    }

    public Category getCategory() {
        return category;
    }

    public String getDescription() {
        return description;
    }

    public double getPrice() {
        return price;
    }

    public int getStock() {
        return stock;
    }

    private final String description;
    private final double price;
    private final int stock;
    private final Category category;
}

产品类:

public class Producto extends Product {
    private int cantidad;

    public Producto(String description, double price, int stock, Category category) {
        super(description, price, stock, category);
        this.cantidad = 1;
    }

    public int getCantidad() {
        return cantidad;
    }

    public void setCantidad(int i) {
        cantidad = i;
    }
}

FXML代码:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuButton?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>

<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="configuradordepc.controller.ControladorView">
   <children>
      <MenuBar>
         <menus>
            <Menu mnemonicParsing="false" text="Archivo">
               <items>
                  <MenuItem fx:id="mNew" mnemonicParsing="false" text="Nuevo" />
                  <MenuItem fx:id="mOpen" mnemonicParsing="false" text="Abrir" />
                  <MenuItem fx:id="mSave" mnemonicParsing="false" text="Guardar" />
                  <MenuItem fx:id="mPrint" mnemonicParsing="false" text="Imprimir" />
               </items>
            </Menu>
         </menus>
      </MenuBar>
      <Accordion VBox.vgrow="ALWAYS">
         <panes>
            <TitledPane animated="false" text="Nuevo PC">
               <content>
                  <VBox fx:id="vBox" spacing="10.0">
                     <children>
                        <HBox spacing="10.0" VBox.vgrow="ALWAYS">
                           <children>
                              <VBox alignment="TOP_CENTER" spacing="10.0">
                                 <children>
                                    <Label text="Filtrar Productos">
                                       <font>
                                          <Font name="System Bold" size="12.0" />
                                       </font>
                                    </Label>
                                    <HBox alignment="CENTER">
                                       <children>
                                          <Label prefWidth="87.0" text="Nombre" />
                                          <TextField fx:id="tFName" HBox.hgrow="ALWAYS" />
                                       </children>
                                    </HBox>
                                    <MenuButton fx:id="mCategory" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Categoría">
                                       <items>
                                          <MenuItem fx:id="mMother" mnemonicParsing="false" onAction="#onSelect" text="Placas base" />
                                          <MenuItem fx:id="mCPU" mnemonicParsing="false" onAction="#onSelect" text="Procesadores" />
                                          <MenuItem fx:id="mRAM" mnemonicParsing="false" onAction="#onSelect" text="Memorias RAM" />
                                          <MenuItem fx:id="mGPU" mnemonicParsing="false" onAction="#onSelect" text="Tarjetas gráficas" />
                                          <MenuItem fx:id="mHDD" mnemonicParsing="false" onAction="#onSelect" text="HDD" />
                                          <MenuItem fx:id="mSSD" mnemonicParsing="false" onAction="#onSelect" text="SSD" />
                                          <MenuItem fx:id="mCase" mnemonicParsing="false" onAction="#onSelect" text="Torres" />
                                          <MenuItem fx:id="mKey" mnemonicParsing="false" onAction="#onSelect" text="Teclados" />
                                          <MenuItem fx:id="mMouse" mnemonicParsing="false" onAction="#onSelect" text="Ratones" />
                                          <MenuItem fx:id="mScreen" mnemonicParsing="false" onAction="#onSelect" text="Monitores" />
                                          <MenuItem fx:id="mSpeak" mnemonicParsing="false" onAction="#onSelect" text="Altavoces" />
                                          <MenuItem fx:id="mMulti" mnemonicParsing="false" onAction="#onSelect" text="Multilectores" />
                                          <MenuItem fx:id="mDVD" mnemonicParsing="false" onAction="#onSelect" text="Grabadoras" />
                                          <MenuItem fx:id="mFan" mnemonicParsing="false" onAction="#onSelect" text="Ventiladores" />
                                          <MenuItem fx:id="mPower" mnemonicParsing="false" onAction="#onSelect" text="Fuentes de alimentación" />
                                       </items>
                                    </MenuButton>
                                    <HBox alignment="CENTER_LEFT">
                                       <children>
                                          <Label prefWidth="87.0" text="Precio Mín." />
                                          <TextField fx:id="tFMin" HBox.hgrow="ALWAYS" />
                                       </children>
                                    </HBox>
                                    <HBox alignment="CENTER_LEFT">
                                       <children>
                                          <Label prefWidth="87.0" text="Precio Máx." />
                                          <TextField fx:id="tFMax" HBox.hgrow="ALWAYS" />
                                       </children>
                                    </HBox>
                                    <HBox alignment="CENTER" spacing="10.0">
                                       <children>
                                          <Button fx:id="bAccept" mnemonicParsing="false" onAction="#onAccept" text="Aceptar" />
                                          <Button fx:id="bCancel" mnemonicParsing="false" onAction="#onCancel" text="Cancelar" />
                                       </children>
                                    </HBox>
                                 </children>
                                 <HBox.margin>
                                    <Insets top="4.0" />
                                 </HBox.margin>
                              </VBox>
                              <VBox alignment="CENTER" spacing="10.0" HBox.hgrow="ALWAYS">
                                 <HBox.margin>
                                    <Insets />
                                 </HBox.margin>
                                 <children>
                                    <TableView fx:id="tableViewItem" VBox.vgrow="ALWAYS">
                                       <columns>
                                          <TableColumn editable="false" prefWidth="75.0" sortable="false" text="Productos">
                                             <columns>
                                                <TableColumn fx:id="nameItemColumn" editable="false" prefWidth="75.0" sortable="false" text="Nombre" />
                                                <TableColumn fx:id="priceColumn" editable="false" prefWidth="75.0" sortable="false" text="Precio" />
                                                <TableColumn fx:id="availableColumn" editable="false" prefWidth="75.0" sortable="false" text="Disponibilidad" />
                                             </columns>
                                          </TableColumn>
                                       </columns>
                                       <columnResizePolicy>
                                          <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
                                       </columnResizePolicy>
                                    </TableView>
                                    <Button fx:id="bAdd" mnemonicParsing="false" onAction="#onAdd" text="Añadir" />
                                 </children>
                              </VBox>
                              <VBox spacing="10.0" HBox.hgrow="ALWAYS">
                                 <children>
                                    <TableView fx:id="tableViewBudget" editable="true" VBox.vgrow="ALWAYS">
                                       <columns>
                                          <TableColumn prefWidth="75.0" sortable="false" text="Presupuesto">
                                             <columns>
                                                <TableColumn fx:id="nameBudgetColumn" editable="false" prefWidth="75.0" sortable="false" text="Nombre" />
                                                <TableColumn fx:id="outTaxColumn" editable="false" prefWidth="75.0" sortable="false" text="Sin IVA" />
                                                <TableColumn fx:id="inTaxColumn" editable="false" prefWidth="75.0" sortable="false" text="Con IVA" />
                                                <TableColumn fx:id="quantityColumn" prefWidth="75.0" sortable="false" text="Cantidad" />
                                             </columns>
                                          </TableColumn>
                                       </columns>
                                       <columnResizePolicy>
                                          <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
                                       </columnResizePolicy>
                                    </TableView>
                                    <HBox alignment="CENTER" spacing="10.0">
                                       <children>
                                          <Button fx:id="bRemove" mnemonicParsing="false" onAction="#onRemove" text="Eliminar" />
                                          <Button fx:id="bClear" mnemonicParsing="false" onAction="#onClear" text="Limpiar" />
                                       </children>
                                    </HBox>
                                 </children>
                              </VBox>
                           </children>
                        </HBox>
                     </children>
                     <padding>
                        <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
                     </padding>
                  </VBox>
               </content>
            </TitledPane>
            <TitledPane animated="false" text="Configuraciones" />
         </panes>
      </Accordion>
   </children>
</VBox>

2 个答案:

答案 0 :(得分:1)

您可以使用Map<Product, ObjectProperty<Integer>>来存储数量。

final int defaultValue = 0;

Map<StringItem, ObjectProperty<Integer>> map = new HashMap<>();

// fill map with existing keys
budgetData.forEach(i -> map.put(i, new SimpleObjectProperty(defaultValue)));

// update map on change of list
budgetData.addListener((ListChangeListener.Change<? extends StringItem> c) -> {
    while (c.next()) {
        c.getRemoved().forEach(map::remove);
        c.getAddedSubList().forEach(i -> map.put(i, new SimpleObjectProperty(defaultValue)));
    }
});

// use value in map as value for column
quantityColumn.setCellValueFactory(d -> map.get(d.getValue()));
quantityColumn.setCellFactory(TextFieldTableCell.forTableColumn(new IntegerStringConverter()));

请注意,这要求列表中的所有项目与equals成对不同。如果不满足此条件,则必须使用唯一键作为TableView的项目类型,并将数量和原始项目类型关联到地图中。

答案 1 :(得分:0)

您需要使用单元工厂来实现:

nameBudgetColumn.setCellFactory(tc -> new TextFieldTableCell<>());