1

In one part of my application I need to make a search engine that will search the database and display the result in a ListView. However, depending on the mode of my search, sometimes I want to display one value per row and sometimes multiple values. For example: when I search for artists I want only artist names to be displayed; when I search for song title, then I want artist name, song title, and album displayed in each row.

I create a custom cell for my list view and create a simple item (one string) and item that extends that simple item (acquires two more strings). I get "incompatbile types" error when I try to set ObservableList<MyItem> to ListView<MyExtendedItem>.

Is there a way to do this?

Here is the example code:

    public class ListViewProblem extends Application {

    @Override
    public void start(Stage primaryStage) {

        ListView<MyExtendedItem> listView = new ListView();
        listView.setCellFactory((ListView<MyExtendedItem> list) -> new MyCell());

        listView.setItems(simpleSearch());
        listView.setItems(extendedSearch());

        StackPane root = new StackPane();
        root.getChildren().add(listView);

        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    public ObservableList<MyItem> simpleSearch() {
        return simpleListFromDatabase();
    }

    public ObservableList<MyExtendedItem> extendedSearch() {
        return extendedListFromDatabase();
    }

}

Simple item has one string:

public class MyItem {
    String artist;

    public boolean isExtended(){
        return false;
    }

    //... getter method for artist
}

Extended item has multiple attributes:

public class MyExtendedItem extends MyItem {
    String title;
    String album;

    @Override
    public boolean isExtended() {
        return true;
    }

    //... getter methods for title and album
}

Custom cell class that checks if the item is extended or simple and displays the data accordingly:

public class MyCell extends ListCell<MyExtendedItem>{

    public MyCell() {};

    @Override
    protected void updateItem(MyExtendedItem item, boolean empty) {
        super.updateItem(item, empty);
        if (item != null) {
            if(item.isExtended())
            {
                Label label1 = new Label(item.getArtist());
                Label label2 = new Label(item.getTitle());
                Label label3 = new Label(item.getAlbum()); 

                HBox hBox = new HBox(label1, label2, label3);
                setGraphic(hBox);
            }
            else {
                Label label1 = new Label(item.Artist());
                HBox hBox = new HBox(label1);
                setGraphic(hBox);
            }
        }
    }
}
jankok
  • 11
  • 2
  • Why not use a `TableView` with one or three columns depending on the search? – eckig Aug 27 '15 at 08:40
  • I would like the text to be written as follows "Artist - Title (Album)" as it is one string and not separated in different columns. – jankok Aug 27 '15 at 08:45
  • Make it a `ListView`. You can either do a downcast in the `ListCell` implementation when you know you have an `ExtendedItem`, or just use a single `Label` in either case and provide a method that returns the correctly formatted `String`. (If you just override `toString()` in both classes, you can get rid of the cell factory entirely, though you may want `toString()` to do something else entirely for other reasons.) – James_D Aug 27 '15 at 11:39

0 Answers0