简体   繁体   English

每个选定项目的JavaFX ComboBox背景颜色

[英]JavaFX ComboBox background color per selected item

I would like to change background of a ComboBox based on selected item. 我想根据所选项目更改ComboBox的背景。

For example: if selected first item then background should be green, if second one is selected then red. 例如:如果选择了第一项,则背景应为绿色,如果选择了第二项,则背景应为红色。

Is this possible? 这可能吗?

Sure this is possible. 当然可以。 Create custom ListCell s in a cellFactory you use with the ComboBox and use it to modify the Cell 's style based on the item it contains. 在与ComboBox使用的cellFactory创建自定义ListCell ,并根据它包含的项目使用它来修改Cell的样式。

Example: 例:

public class Item {

    public Item(String value, Color color) {
        this.value = value;
        this.color = color;
    }

    private final String value;
    private final Color color;

    public String getValue() {
        return value;
    }

    public Color getColor() {
        return color;
    }
}
ComboBox<Item> comboBox = new ComboBox<>(FXCollections.observableArrayList(
        new Item("Summer", Color.RED),
        new Item("Winter", Color.CYAN),
        new Item("Spring", Color.LIME),
        new Item("Autumn", Color.BROWN)
));

comboBox.setCellFactory(lv -> new ListCell<Item>(){

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

        if (empty || item == null) {
            setBackground(Background.EMPTY);
            setText("");
        } else {
            setBackground(new Background(new BackgroundFill(item.getColor(),
                                                            CornerRadii.EMPTY,
                                                            Insets.EMPTY)));
            setText(item.getValue());
        }
    }

});

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

If you want to just set the color of the ComboBox itself and not the items of the ComboBox inside the drop-down list, you can create a custom binding between the buttonCellProperty and the valueProperty of the ComboBox to implement the custom coloring. 如果只想设置ComboBox本身的颜色,而不是下拉列表中ComboBox的项目,则可以在buttonCellPropertyComboBoxvalueProperty之间创建自定义绑定,以实现自定义着色。

Example

This example colors the ComboBox to green if the first item is selected, to red if the second item is selected, and leaves the coloring as it is otherwise. 本示例将ComboBox颜色选择为绿色(如果选择了第一项),将其着色为红色(如果选择了第二项),否则将颜色保持不变。

Update: The background color of the arrow button of the ComboBox is also colored now, for that the lookup method can be used to get the arrow button: StackPane arrowButton = (StackPane) combo.lookup(".arrow-button"); 更新:现在, ComboBox的箭头按钮的背景色也已着色,因为可以使用查找方法来获取箭头按钮: StackPane arrowButton = (StackPane) combo.lookup(".arrow-button"); .

ComboBox<String> combo = new ComboBox<>();
combo.setItems(FXCollections.observableArrayList("First", "Second", "Third", "Fourth"));

combo.buttonCellProperty().bind(Bindings.createObjectBinding(() -> {

    int indexOf = combo.getItems().indexOf(combo.getValue());

    Color color = Color.TRANSPARENT;

    switch (indexOf) {
    case 0: color = Color.GREEN; break;
    case 1: color = Color.RED; break;
    default: break;
    }

    final Color finalColor = color;

    // Get the arrow button of the combo-box
    StackPane arrowButton = (StackPane) combo.lookup(".arrow-button");


    return new ListCell<String>() {

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

            if (empty || item == null) {
                setBackground(Background.EMPTY);
                setText("");
            } else {
                setBackground(new Background(new BackgroundFill(finalColor, CornerRadii.EMPTY, Insets.EMPTY)));
                setText(item);
            }

            // Set the background of the arrow also
            if (arrowButton != null)
                arrowButton.setBackground(getBackground());
        }

    };
}, combo.valueProperty()));

The result is like: 结果是这样的:

在此处输入图片说明

Notes 笔记

1) If you want to color the items also in the drop-down list, you can pick the solution from other answers here. 1)如果您还要在下拉列表中为项目着色,则可以从此处的其他答案中选择解决方案。

2) If you do not display String s but items that are able to store also the color of the item, the solution is even shorter, just use the color of the selected item in updateItem method rather than calculating your own color. 2)如果您不显示String而是能够存储项目颜色的项目,则解决方案甚至更短,只需在updateItem方法中使用所选项目的颜色,而不是计算自己的颜色即可。

 public class Main extends Application {

Random r = new Random();
private class Item {
    Color c;
    String s;
    public Item(Color a,String b){
        c = a;
        s = b;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return s;
    }
}

private void addAll(List<String> items){
    for(String s : items){
        box.getItems().add(new Item(Color.WHITE,s));
    }
}

ComboBox<Item> box;

@Override
public void start(Stage primaryStage) {

    Pane p;

    try {
        p = new StackPane();
        box = new ComboBox<Item>();
        box.setMinWidth(100);
        addAll(Font.getFontNames());
        box.setCellFactory(new Callback<ListView<Item>, ListCell<Item>>() {

            @Override
            public ListCell<Item> call(ListView<Item> param) {
                // TODO Auto-generated method stub
                return new ListCell<Item>(){


                    @Override
                    public void updateSelected(boolean selected) {
                        super.updateSelected(selected);
                        if(selected){
                            getItem().c = Color.rgb(r.nextInt(205),
                                    r.nextInt(205), r.nextInt(205), 1);

                        }
                        setStyle("-fx-text-fill: black; -fx-background-color: #" +
                                getItem().c.toString().substring(2)+";");
                    }

                    @Override
                    protected void updateItem(Item item, boolean empty) {
                        // TODO Auto-generated method stub
                        super.updateItem(item, empty);
                        if(empty){
                            return;
                        }
                        setText(item.toString());
                        setStyle("-fx-text-fill: black; -fx-background-color: #" +
                                getItem().c.toString().substring(2)+";");
                    }

                };
            }
        });
        p.getChildren().add(box);
        p.setPrefSize(500, 500);
        Scene scene = new Scene(p);
        scene.getStylesheets().add(getClass().
                getResource("application.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();

    } catch(Exception e) {
        e.printStackTrace();
    }
}
    combobox.valueProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue ov, String t, String t1) {
            if (t1.equals("Option 1")) {
               combobox.setStyle(" -fx-background-color: #000000");
            }
            if (t1.equals("Option 2")) {
                combobox.setStyle(" -fx-background-color: #FFFFFF");
            }
        }
    });

you should be able to do something quite simple like the above with a basic change listener, you may have to refresh the page (I often just remove and re-add the component so you can see the change take place) 您应该能够使用基本的更改侦听器来完成类似上述的操作,您可能需要刷新页面(我通常只是删除并重新添加组件,以便可以看到更改发生了)

This is on the basis you want to select a combobox item then the box to change, not each item to have a different colour from the start 这是基于您要选择一个组合框项目然后更改该框的基础,而不是每个项目从一开始就具有不同的颜色

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

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