我的 JavaFX 应用程序出现 ClassCasting 错误,并且值出现在 tableView 上

ClassCasting Error on my JavaFX Application and Issue with Values showing up on tableView

一切正常,但后来我添加了泛型,现在这个 ClassCastException 不断弹出,我不知道为什么。

****重要****
所以我也尝试删除它,但这是另一个问题出现的地方。打印直到牵引力控制栏的所有值。在此之后,所有的值都不会出现在事件中,尽管除了其中一些的数据类型之外,一切都完全相同。

错误

Caused by: java.lang.ClassCastException: app.westminster.car.rentalSystem.Car cannot be cast to app.westminster.car.rentalSystem.Motorbike at app.westminster.car.rentalSystem.GUI.MainGUI.lambda$start(MainGUI.java:139) at javafx.scene.control.TableColumn.getCellObservableValue(TableColumn.java:578) at javafx.scene.control.TableColumn.getCellObservableValue(TableColumn.java:563) at javafx.scene.control.TableCell.updateItem(TableCell.java:644) at javafx.scene.control.TableCell.indexChanged(TableCell.java:468) at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116) at com.sun.javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:533) at com.sun.javafx.scene.control.skin.TableRowSkinBase.init(TableRowSkinBase.java:147) at com.sun.javafx.scene.control.skin.TableRowSkin.(TableRowSkin.java:64) at javafx.scene.control.TableRow.createDefaultSkin(TableRow.java:212) at javafx.scene.control.Control.impl_processCSS(Control.java:872) at javafx.scene.Node.processCSS(Node.java:9056) at javafx.scene.Node.applyCss(Node.java:9153) at com.sun.javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1964) at com.sun.javafx.scene.control.skin.VirtualFlow.getCell(VirtualFlow.java:1797) at com.sun.javafx.scene.control.skin.VirtualFlow.getCellLength(VirtualFlow.java:1879) at com.sun.javafx.scene.control.skin.VirtualFlow.computeViewportOffset(VirtualFlow.java:2528) at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1189) at javafx.scene.Parent.layout(Parent.java:1087) at javafx.scene.Parent.layout(Parent.java:1093) at javafx.scene.Parent.layout(Parent.java:1093) at javafx.scene.Scene.doLayoutPass(Scene.java:552) at javafx.scene.Scene.preferredSize(Scene.java:1646) at javafx.scene.Scene.impl_preferredSize(Scene.java:1720) at javafx.stage.Window.invalidated(Window.java:864) at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:109) at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:144) at javafx.stage.Window.setShowing(Window.java:940) at javafx.stage.Window.show(Window.java:955) at javafx.stage.Stage.show(Stage.java:259) at app.westminster.car.rentalSystem.GUI.MainGUI.start(MainGUI.java:154) at com.sun.javafx.application.LauncherImpl.lambda$launchApplication11(LauncherImpl.java:863) at com.sun.javafx.application.PlatformImpl.lambda$runAndWait4(PlatformImpl.java:326) at com.sun.javafx.application.PlatformImpl.lambda$null2(PlatformImpl.java:295) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.application.PlatformImpl.lambda$runLater3(PlatformImpl.java:294) at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null7(WinApplication.java:177) ... 1 more

GUI Class

public class MainGUI extends Application {

private static Stage stage;

@Override
public void start(Stage primaryStage) throws Exception {

    stage = primaryStage;
    Platform.setImplicitExit(false);

    stage.setTitle("Westminster Rentals");
    VBox mainLayout = new VBox();

    Scene scene = new Scene(mainLayout, 1655,800);

    Label heading1 = new Label("Welcome to Westminster Rentals");
    heading1.setStyle("-fx-font-size: 32px; -fx-font-family: -apple-system, sans-serif;");
    heading1.setPadding(new Insets(20,20,20,20));


    //_____________________Search Tab__________________________________//

    // search Tab will hold search bar, search button and rent button

    HBox searchTab = new HBox();
    searchTab.setStyle("-fx-spacing: 10px; -fx-padding: 20px");

    JFXButton searchButton = new JFXButton("Search");
    searchButton.setAlignment(Pos.CENTER);
    searchButton.setStyle("-fx-padding: 20px;-fx-background-color: #6143d5; -fx-text-fill: #fff;");

    JFXTextField searchBar = new JFXTextField();
    searchBar.setPrefWidth(500);
    searchBar.setStyle("-fx-padding: 20px;");
    searchBar.promptTextProperty().setValue("Search....");

    HBox rentTab = new HBox();
    JFXButton rent = new JFXButton("Rent a car");
    rent.setOnAction(e->{
        RentGUI.showRentPage();
    });
    rent.setStyle("-fx-padding: 20px;-fx-background-color: #1ad541; -fx-text-fill: #fff;");


    rentTab.getChildren().add(rent);
    searchTab.getChildren().addAll(searchBar,searchButton, rentTab);

    //_____________________Search Tab --END--_____________________________//


    //Main Heading will hold a vertical alignment for heading1 and the searchTab Hbox to create embedded layout
    VBox mainHeading =  new VBox();
    mainHeading.getChildren().addAll(heading1,searchTab);

    //Table view and Table columns are used to build the table attribute of the app
    // This needs to be done as below unless FXML is used to build the application
    TableView<Vehicle> tableView = new TableView<>();
    tableView.setEditable(false);

    TableColumn<Vehicle, String> makeColumn = new TableColumn<>("Make");
    makeColumn.setPrefWidth(150);
    makeColumn.setCellValueFactory(data->  new SimpleStringProperty(data.getValue().getMake()));

    TableColumn<Vehicle,String> modelColumn = new TableColumn<>("Model");
    modelColumn.setPrefWidth(200);
    modelColumn.setCellValueFactory(new PropertyValueFactory<>("model"));

    TableColumn<Vehicle,String> plateNumColumn = new TableColumn<>("Plate Number");
    plateNumColumn.setPrefWidth(200);
    plateNumColumn.setCellValueFactory(new PropertyValueFactory<>("plateNumber"));

    TableColumn<Vehicle,String> fuelTypeColumn = new TableColumn<>("Fuel Type");
    fuelTypeColumn.setPrefWidth(200);
    fuelTypeColumn.setCellValueFactory(new PropertyValueFactory<>("fuelType"));

    TableColumn<Vehicle, BigDecimal> priceColumn = new TableColumn<>("Price Per Hour (USD)");
    priceColumn.setPrefWidth(200);
    priceColumn.setCellValueFactory(new PropertyValueFactory<>("pricePerHour"));

    TableColumn<Vehicle,String> transmissionColumn = new TableColumn<>("Transmission");
    transmissionColumn.setPrefWidth(200);
    transmissionColumn.setCellValueFactory(new PropertyValueFactory<>("transmission"));

    TableColumn carColumn = new TableColumn("Car");
    carColumn.setPrefWidth(200);
    carColumn.setCellValueFactory(new PropertyValueFactory("car"));

    TableColumn<Car,Boolean> tractionControlColumn = new TableColumn<>("Traction Control?");
    tractionControlColumn.setPrefWidth(200);
    tractionControlColumn.setCellValueFactory(new PropertyValueFactory<>("tractionControl"));

    TableColumn<Car,Boolean> appleCarPlayColumn = new TableColumn<>("Apple Car Play?");
    appleCarPlayColumn.setPrefWidth(200);
    appleCarPlayColumn.setCellValueFactory(data-> new SimpleBooleanProperty(data.getValue().hasAppleCarPlay()));

    TableColumn <Car,String>parkingAssistanceColumn = new TableColumn<>("Parking Assistance?");
    parkingAssistanceColumn.setPrefWidth(200);
    parkingAssistanceColumn.setCellValueFactory(data-> new SimpleStringProperty(String.valueOf(data.getValue().hasParkingAssistant())));

    TableColumn<Car,String> blindSpotAwarenessColumn = new TableColumn<>("Blind spot awareness?");
    blindSpotAwarenessColumn.setPrefWidth(200);
    blindSpotAwarenessColumn.setCellValueFactory(data-> new SimpleStringProperty(String.valueOf(data.getValue().hasBlindSpotAwareness())));

    TableColumn bikeColumn = new TableColumn("Motorbikes");
    bikeColumn.setPrefWidth(200);
    bikeColumn.setCellValueFactory(new PropertyValueFactory("motorbike"));

    TableColumn<Motorbike, Boolean> basketColumn = new TableColumn<>("Basket?");
    basketColumn.setPrefWidth(200);
    basketColumn.setCellValueFactory(data-> new SimpleBooleanProperty(data.getValue().hasBasket()));

    TableColumn<Motorbike, Boolean> gyroColumn = new TableColumn<>("Gyroscopic Balance?");
    gyroColumn.setPrefWidth(200);
    gyroColumn.setCellValueFactory(data-> new SimpleBooleanProperty(data.getValue().hasGyroscopicBalance()));


    carColumn.getColumns().addAll(tractionControlColumn,appleCarPlayColumn,parkingAssistanceColumn,blindSpotAwarenessColumn);
    bikeColumn.getColumns().addAll(basketColumn,gyroColumn);
    tableView.getColumns().addAll(makeColumn,modelColumn,plateNumColumn,fuelTypeColumn,priceColumn,transmissionColumn,carColumn,bikeColumn);

    mainLayout.getChildren().addAll(mainHeading, tableView);
    tableView.setItems(addTableItems());

    stage.setScene(scene);
    stage.show();

}


//addTableItems will create an observable list required to enter values into the table.

private ObservableList<Vehicle> addTableItems() throws UnknownHostException {
    ObservableList<Vehicle> musicItem = FXCollections.observableArrayList();
    for (Vehicle item: Database.getDatastore().find(Vehicle.class).asList()){
        musicItem.addAll(item);
    }
    return musicItem;
}

public static void main(){
    launch();
}

public static void showStage(){
    stage.show();
}
}

Main Class 和 Main 方法

public class Main extends Thread{

private static Scanner scanner = new Scanner(System.in);
private static Stage stage;

public static void main(String[] args) {
    int userResponse;
    RentalVehicleManager rentalVehicleManager = new WestminsterRentalVehicleManager();
    Thread guiControlThread = new Thread(MainGUI::main);
    guiControlThread.start();
}

}

假设我删除了 lambda 并放入了新的 PropertyValueFactory。然后错误消失,GUI 工作

但是

牵引力控制后的数值不显示

TableView (Vehicle) 的类型参数与您用于某些列的第一个类型参数之间存在差异。这两个类型参数应该匹配。否则会发生这样的事情。

由于 VehicleTableView 的类型参数,编译器允许您将可分配给 Vehicle 的所有内容添加到该 TableViewitems 列表中=].

basketColumn 声明为 TableColumn<Motorbike, Boolean> basketColumn "tells" 编译器认为 table 中的所有项目都是 Motorbike。由于这个原因,以下代码片段会在编译后的代码中产生相同的结果:

TableColumn basketColumn = new TableColumn("Basket?"); // note the use of the raw type here
basketColumn.setPrefWidth(200);

// note the hidden cast inserted here by the compiler based on the type parameter in the declaration
// this is the cause of the ClassCastException
basketColumn.setCellValueFactory(data -> new SimpleBooleanProperty(((Motorbike) data.getValue()).hasBasket()));

因为您想将 CarMotorbike 都放入 TableView,您需要 return 根据 cellValueFactorys:

TableColumn<Vehicle, Boolean> basketColumn = new TableColumn<>("Basket?");
basketColumn.setPrefWidth(200);
basketColumn.setCellValueFactory(data -> {
    Vehicle item = data.getValue();
    if (item instanceof Motorbike) {
        return new SimpleBooleanProperty(((Motorbike) item).hasBasket());
    } else {
        return null; // put something else here, if you don't want empty cells for non Motorbikes
    }
});

您的代码中还有多个其他地方需要像这样进行更改。