简体   繁体   English

javafx.scene.control.TableColumn 不能转换为 javafx.scene.control.TableColumn$CellDataFeatures

[英]javafx.scene.control.TableColumn cannot be cast to javafx.scene.control.TableColumn$CellDataFeatures

I have a problem when it comes to filling a javafx tableview.我在填充 javafx tableview 时遇到问题。

I am currently working on a GUI based event management tool (for university) and I am stuck trying to fill a Tableview list, that should be in the center of a border pane layout.我目前正在开发基于 GUI 的事件管理工具(适用于大学),但我一直在尝试填充 Tableview 列表,该列表应该位于边框窗格布局的中心。

This is my code (its pretty long thought, its the main window function):这是我的代码(它的想法很长,它的主窗口函数):

import java.sql.Date;
import java.sql.SQLException;
import java.util.List;

//--main imports--//
import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Label;
//--table imports--//
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.TableColumn;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class MainWindow extends Application {


private static Label tableHeadline;
private static TableView table;
private static TableColumn dateCol;
private static TableColumn nameCol;
private static TableColumn numberOfGuestsCol;
private static TableColumn locationCol;

private static BorderPane layout;

//This is just some test data, this is where the program crashes, I think
final static ObservableList<Event> data =  FXCollections.observableArrayList(
        new Event("Jacob", "Smith", 30, new Date(10000))
        );
//----------------------//

//--Private constants--//   
private static final String DATE = "Date";
private static final String NAME = "Name";
private static final String NUMBER_OF_GUESTS = "Number of guests";
private static final String LOCATION = "Location";
//---------------------//


/**The main method, launching the application*/
public static void main(String[] args) {
    try {
    //--launching the application with given arguments--//
    launch(args);}
    catch (Exception e) {e.printStackTrace();}
}

/**
 * The start-method, that is called first when 'launch' is used
 */
@Override
public void start(Stage primaryWindow) throws Exception {

    //--initialize all the objects in the window--//
    initializeObjects();

    //--get the layout--//
    initializeLayout();

    //--give functionality to the objects in the window--//
    functionalizeObjects();

    //--create the new scene--//
    Scene main = new Scene(layout);

    //--Giving the main window a title and bringing it up front--//
    primaryWindow.setMinHeight(DEFAULT_WIN_HEIGHT);
    primaryWindow.setMinWidth(DEFAULT_WIN_WIDTH);
    primaryWindow.setScene(main);
    primaryWindow.show();

    //TODO: on window close, save the content of the list to the db
    primaryWindow.setOnCloseRequest(null);
}


/**
 * Initializes all given elements of the main window by creating and naming them
 */
private static void initializeObjects () {
    //--table--//
    tableHeadline = new Label (TABLE_HEAD);
    tableHeadline.setFont(new Font ("Arial", 20));

    table = new TableView<>();

    table.setEditable(true);

    //--date column--//
    dateCol = new TableColumn<Event, Date>(DATE);
    dateCol.setCellFactory(
            new PropertyValueFactory<>("Date")
        );

    //--name column--//
    nameCol = new TableColumn<Event, String>(NAME);
    nameCol.setCellValueFactory(
            new PropertyValueFactory<>("name")
        );      

    //--numberOfGuests column--//
    numberOfGuestsCol = new TableColumn<Event, Integer>(NUMBER_OF_GUESTS);
    numberOfGuestsCol.setMinWidth(150);
    numberOfGuestsCol.setCellValueFactory(
            new PropertyValueFactory<>("Number of Guests")
        );

    //--location column--//
    locationCol = new TableColumn<Event, String>(LOCATION);
    locationCol.setCellValueFactory(
            new PropertyValueFactory<>("location")
        );

        table.setItems(data);
        table.getColumns().addAll(nameCol,locationCol,
                numberOfGuestsCol,dateCol);

    //TODO fill with data from the database
    //--end table--//
}

/**
 * Assign functionality to the elements of the main window
 */
private static void functionalizeObjects () {

    //--new... MenuItem--//
    newMItem.setOnAction(e -> {
        createReturn = CreatePopup.display();

        if (createReturn) {
            //--get the user input--//
            List<Object> toCreate = CreatePopup.getInput();

            //--add a new event according to the user input to the list--//
           //This is where new Events should be inserted, but I cannot test this as I do not come that far
            final ObservableList<Event>data = FXCollections.ObservableArrayList(
                    new Event(toCreate(0),toCreate(1),toCreate(2),toCreate(3))
                    );

            }
        }
    });

    });

}

/**
 * Initializes the layout of the main window
 */
private static void initializeLayout() {
    //--Create a new layout--//
    layout = new BorderPane();

    layout.setTop(menuBar);
    layout.setCenter(table);
}

public static class Event {
    private final SimpleStringProperty name;
    private final SimpleStringProperty location;
    private final SimpleIntegerProperty numberOfGuests;
    private final SimpleObjectProperty<Date> date;

    private Event(String name, String location, int numOfGuests, Date date) {
        this.name = new SimpleStringProperty(name);
        this.location = new SimpleStringProperty(location);
        this.numberOfGuests = new SimpleIntegerProperty(numOfGuests);
        this.date = new SimpleObjectProperty<Date>(date);
    }


    //--------//
    // Getter //
    //--------//

    public SimpleStringProperty getName() {
        return name;
    }

    public SimpleStringProperty getLocation() {
        return location;
    }

    public SimpleIntegerProperty getNumberOfGuests() {
        return numberOfGuests;
    }

    public SimpleObjectProperty<Date> getDate() {
        return date;
    }

}

}

This code will give me an error:这段代码会给我一个错误:

    Exception in Application start method
Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: javafx.scene.control.TableColumn cannot be cast to javafx.scene.control.TableColumn$CellDataFeatures
    at javafx.scene.control.cell.PropertyValueFactory.call(PropertyValueFactory.java:98)
    at com.sun.javafx.scene.control.skin.TableRowSkin.getCell(TableRowSkin.java:87)
    at com.sun.javafx.scene.control.skin.TableRowSkin.getCell(TableRowSkin.java:53)
    at com.sun.javafx.scene.control.skin.TableRowSkinBase.createCell(TableRowSkinBase.java:698)
    at com.sun.javafx.scene.control.skin.TableRowSkinBase.recreateCells(TableRowSkinBase.java:692)
    at com.sun.javafx.scene.control.skin.TableRowSkinBase.init(TableRowSkinBase.java:146)
    at com.sun.javafx.scene.control.skin.TableRowSkin.<init>(TableRowSkin.java:64)
    at javafx.scene.control.TableRow.createDefaultSkin(TableRow.java:212)
    at javafx.scene.control.Control.impl_processCSS(Control.java:859)
    at javafx.scene.Parent.impl_processCSS(Parent.java:1272)
    at javafx.scene.Parent.impl_processCSS(Parent.java:1272)
    at javafx.scene.Parent.impl_processCSS(Parent.java:1272)
    at javafx.scene.control.Control.impl_processCSS(Control.java:855)
    at javafx.scene.Node.processCSS(Node.java:9056)
    at javafx.scene.Node.processCSS(Node.java:9049)
    at javafx.scene.Scene.doCSSPass(Scene.java:545)
    at javafx.scene.Scene.access$3600(Scene.java:159)
    at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2392)
    at com.sun.javafx.tk.Toolkit.lambda$runPulse$31(Toolkit.java:348)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:347)
    at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:374)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$405(QuantumToolkit.java:319)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$null$50(GtkApplication.java:139)
    at java.lang.Thread.run(Thread.java:745)

I cannot think of any reason for this strange Error.我想不出这个奇怪错误的任何原因。 I also searched pretty long now and tried pretty many things, but it still appears on startup.我现在也搜索了很长时间并尝试了很多东西,但它仍然出现在启动时。

Now I am counting on you, community, please help me!现在我指望你了,社区,请帮助我!

Thanks in advance for reading the long post..提前感谢您阅读长篇文章..

You have你有

dateCol.setCellFactory(...);

instead of代替

dateCol.setCellValueFactory(...);

This is a good example of why you should not use raw types in your code, and should avoid API like PropertyValueFactory in favor of typesafe code.这是一个很好的例子,说明为什么不应该在代码中使用原始类型,并且应该避免像PropertyValueFactory这样的 API 以支持类型安全代码。

Ie you have即你有

TableView table ;
TableColumn dateCol ;

when you should have something like当你应该有类似的东西

TableView<Event> table ;
TableColumn<Event, Date> dateCol ;

And then you can do然后你可以做

dateCol.setCellValueFactory(cellData -> cellData.getValue().getDate());

If you coded it this way, the compiler would have immediately picked up on your error.如果您以这种方式编码,编译器会立即发现您的错误。

As an aside (perhaps, another aside), you should really make your Event class follow the correct JavaFX Properties pattern, as described in the tutorial .顺便说一句(也许是另一边),您真的应该让您的Event类遵循正确的 JavaFX 属性模式,如教程中所述。 You may see unexpected behavior if you don't.如果不这样做,您可能会看到意外行为。

For the future people and Java 11 you can may fix this with that:对于未来的人和 Java 11,您可以通过以下方式解决此问题:

For example, if the Person class is in the com.foo package in the foo.app module, the module-info.java might look like this:例如,如果 Person 类位于 foo.app 模块的 com.foo 包中,则 module-info.java 可能如下所示:

module foo.app { opens com.foo to javafx.base; }

or:或者:

module foo.app {
    opens com.foo; <-- place for with your class
}

https://openjfx.io/javadoc/11/javafx.controls/javafx/scene/control/cell/PropertyValueFactory.html https://openjfx.io/javadoc/11/javafx.controls/javafx/scene/control/cell/PropertyValueFactory.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM