0

I've been having an issue creating a custom cell for list view in JavaFX. In short, I have an observable list of objects (of type BillItem) to create a custom fxml view and add it to the list view.

In the list view, I have just a ListView as the root.

<ListView fx:id="bill" prefWidth="200.0" style="-fx-background-color: yellow;" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="restroid.controllers.left.BillViewController"/>

In the cell view, I have BorderPane in the root and 3 other labels.

<BorderPane fx:id="billItem" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40"
            xmlns:fx="http://javafx.com/fxml/1" fx:controller="restroid.controllers.left.BillItemViewController">
    <left>
        <Label fx:id="numberOfItems" text="2" BorderPane.alignment="CENTER">
            <BorderPane.margin>
                <Insets right="10.0"/>
            </BorderPane.margin>
        </Label>
    </left>
    <center>
        <Label fx:id="itemName" text="Item name" BorderPane.alignment="TOP_LEFT"/>
    </center>
    <right>
        <Label fx:id="price" text="56.00 TL" BorderPane.alignment="CENTER"/>
    </right>
</BorderPane>

When I load the fxml file for the list view, I set up some dummy data in the initialize() method of the responsible controller and set it on the bill (ListView) with setItems(). Finally, using the cell factory, I return a custom ListCell of type BillItem.

@Override
    public void initialize(URL location, ResourceBundle resources) {
        for (int i = 0; i < 10; i++)
            billItems.add(new BillItem(2, "Item name", 56.00));

        observableList = FXCollections.observableList(billItems);

        bill.setItems(observableList);

        bill.setCellFactory(param -> new BillItemCell());
    }

In the updateItem() of the BillItemCell class, I found out that "item" is null and I immediately get the following Exception. There must have been a problem about how I initialize the observable list, though I followed the code examples similar to what I have here.

@Override
protected void updateItem(BillItem item, boolean empty) {
    super.updateItem(item, empty);

    if (item != null) {
        BillItemViewController cell = new BillItemViewController();
        cell.setNumberOfItems(item.getNumberOfItems());
        cell.setItemName(item.getItemName());
        cell.setPrice(item.getPrice());
        setGraphic(cell.getBillItem());
    } else {
        System.out.println("item is null");
    }
}



Exception in Application start method
Exception in thread "main" java.lang.NoSuchMethodException: restroid.MainApp.main([Ljava.lang.String;)
    at java.lang.Class.getMethod(Class.java:1786)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:125)

My first question is, why couldn't the program pass my observable list to the factory?

My other question is about how I'm going to load the custom view to the list view since I never got the chance to test this code because of this issue. I did some digging around and came up with the implementation above. In the BillItemViewController, I'm just loading the custom view and provide the necessary setters.

public BillItemViewController() {
    FXMLLoader fxmlLoader = new FXMLLoader();
    fxmlLoader.setLocation(getClass().getResource("../../views/left/BillItemView.fxml"));
    try {
        fxmlLoader.setController(this);
        fxmlLoader.load();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

Is this a right approach or am I missing something?

enesanbar
  • 49
  • 7
  • 1
    1. I don't understand what you mean by "why couldn't the program pass my observable list to the factory?". Could you elaborate? 2. Have a look at [this answer](http://stackoverflow.com/a/34839491/4185959) on a similar question. 3. Is there a reason you don't use TableView? Is sounds like a better solution for your data. – Itai Jan 17 '16 at 22:43
  • Your error is just that your main application class doesn't have a main method. Just add `public static void main(String[] args) { launch(args); }`. Don't use paths that include `..` when you are using `getClass().getResource(...)`. [They will fail with jar files.](http://stackoverflow.com/questions/34755630/javafx-location-is-not-set-error/34755715#34755715). Also, your `updateItem` method needs to properly handle the case where the item is null (e.g. for empty cells and for cells that have been created but haven't yet been populated); you should set the graphic to `null` in this case. – James_D Jan 17 '16 at 22:46
  • @sillyfly What I meant was that because item is null, I figured the observable list couldn't be passed to the listview properly. – enesanbar Jan 18 '16 at 00:02
  • @James_D FYI, main method is not needed to start a JavaFX application. It's only needed to support some IDEs that couldn't figure out how to start the application. Thanks for the tip, I'll refactor my code. – enesanbar Jan 18 '16 at 00:05
  • Yes, I know that: but you need the main method for IntelliJ to execute your application. The error message you posted clearly states it's looking for the main method. – James_D Jan 18 '16 at 00:07
  • I can say with absolute certainty that IntelliJ doesn't require that. Because I been using it with this project and I've run many JavaFX applications many times. – enesanbar Jan 18 '16 at 00:13

0 Answers0