如何用observableArray填充组合框?

时间:2019-03-13 22:40:17

标签: java javafx

我正在创建一个电影系统,借此用户应该能够通过主页中的组合框选择电影。我在FilmController类中创建了一个Array列表,然后将其转换为observableList,并努力在组合框(HomepageController)中填充其内容。

这是具有arraylist和observableList的FilmController

public class FilmController {

private ArrayList<Film> films = new ArrayList<>();

public FilmController() {
    Film f1 = new Film("Avatar", "James Cameron", "James Cameron",
            "Sam Wortherington" + "Zoe Saldana", "162", "Sci-Fi", 8.50);

    Film f2 = new Film("Black Panther", "Kevin Feige", "Ryan Coogler",
            "Chadwick Boseman" + "Lupita Nyong'o", "135", "Sci-Fi Fantasy", 10.00);

    Film f3 = new Film("Creed 2", "Sylvester Stallone", "Steven Caple Jr",
            "Michael B Jordan" + "Tessa Thompson", "130", "Drama", 10.00);

    Film f4 = new Film("Deadpool", "Simon Kinberg", "Tim Miller",
            "Ryan Reynolds" + "Morena Baccarin", "109", "Sci-Fi", 7.50);

    Film f5 = new Film("A Quiet Place", "Michel Bay", "John Krasinski",
            "Emily Blunt" + "John Krasinski", "91", "Thriller", 8.00);

    films.add(f1);
    films.add(f2);
    films.add(f3);
    films.add(f4);
    films.add(f5);
}

public ArrayList<Film> getFilms() {
    return films;
}

public ObservableList<Film> getOlFilms() {
    return FXCollections.observableArrayList(films);

   }
}

我尝试在HomepageController中实现此功能,但似乎给了我一个错误:

  public class HomepageController {

        public ComboBox cbFilms;

public void initialize() { 
cbFilms.setButtonCell((ListCell) cbFilms.getCellFactory().call(null)); 
}

public void cbListFilms(ActionEvent actionEvent) {
        FilmController f = new FilmController();
        cbFilms.setItems(f.getOlFilms().toArray());
    } 
}

我看过this question,但是它似乎对我没有用。

我希望组合框仅列出影片名称,最好是当鼠标悬停在影片名称上时,如果可能的话,我希望它显示其余属性。

这是组合框的fxml内容:

    <ComboBox fx:id="cbFilms" layoutX="291.0" layoutY="138.0" onAction="#cbListFilms" prefHeight="31.0" prefWidth="230.0"
          promptText="Please select film by name" style="-fx-background-color: tan;">
    <items>
        <FXCollections fx:factory="observableArrayList"/>
    </items>
    <effect>
        <SepiaTone/>
    </effect>
</ComboBox>

2 个答案:

答案 0 :(得分:2)

您应该设置一个CellFactory,以处理ComboBox中的所有项目:

ComboBox<Film> comboBox = new ComboBox<>();
comboBox.setItems(f.getOlFilms());
comboBox.setCellFactory(param -> new ListCell<Film>() {
    @Override
    protected void updateItem(Film item, boolean empty) {
        super.updateItem(item, empty);
        if (item != null) {
            setText(item.getName());
        } else {
            // handle null object
        }
    }
});

此外,您应该为所选项目设置一个ButtonCell。您可以为此创建自己的ListCell,以在视图中添加更多数据,也可以使用与项目相同的数据:

comboBox.setButtonCell(comboBox.getCellFactory().call(null));

作为null值的替代方法,您可以在其中传递默认值。

答案 1 :(得分:2)

您不需要/不想在.toArray()上调用ObservableList方法。 ComboBox.setItems()方法使用ObservableList就可以了:

cbFilms.setItems(f.getOlFilms());

然后,为了使ComboBox仅显示电影的标题,您需要在StringConverter上设置ComboBoxStringConverter基本上获取对象并返回其String表示形式:

cbFilms.setConverter(new StringConverter<Film>() {
    @Override
    public String toString(Film film) {
        return film.getTitle();
    }

    @Override
    public Film fromString(String string) {
        return null;
    }
});

这是一个可以测试的完整示例:

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;

public class SimpleComboBoxExample extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        // Simple interface
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // Create some sample data
        ObservableList<Film> filmsList = FXCollections.observableArrayList();
        filmsList.add(new Film("Titanic", "James Cameron"));
        filmsList.add(new Film("Jaws", "Steven Spielberg"));
        filmsList.add(new Film("The Last Samurai", "Edward Zwick"));

        // Define our ComboBox with our data model as its type
        ComboBox<Film> cboFilms = new ComboBox<>();

        // Use a StringConverter to configure our ComboBox to display only the film's title
        cboFilms.setConverter(new StringConverter<Film>() {
            @Override
            public String toString(Film film) {
                return film.getTitle();
            }

            @Override
            public Film fromString(String string) {
                return null;
            }
        });

        // Finally, set our ComboBox's items to our sample list
        cboFilms.setItems(filmsList);

        root.getChildren().add(cboFilms);

        // Show the Stage
        primaryStage.setWidth(300);
        primaryStage.setHeight(300);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}

// Our data model class
class Film {

    private StringProperty title = new SimpleStringProperty();
    private StringProperty director = new SimpleStringProperty();

    public Film(String title, String director) {
        this.title.set(title);
        this.director.set(director);
    }

    public String getTitle() {
        return title.get();
    }

    public StringProperty titleProperty() {
        return title;
    }

    public String getDirector() {
        return director.get();
    }

    public StringProperty directorProperty() {
        return director;
    }
}

结果:

screenshot