【问题标题】:Text combo box factory call文本组合框工厂调用
【发布时间】:2019-10-21 15:34:12
【问题描述】:

对于我在 Java FX 中的项目,我有一个字符串列表,我需要将它们添加到组合框中,并要求只有其中一个(第一个)被着色为红色。

我考虑过将字符串封装在 Text 中,并使用适当的 setStyle("fx-text-fill: Color.xxx") 将它们添加到组合框中。这需要一个 setCellFactory() 方法,我不知道如何正确设置它。

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Callback;

public class Mainu extends Application 
{
    final ObservableList<Text> SAMPUNITFRONT = FXCollections.observableArrayList(
            new Text("complete"), new Text("seconds"), new Text("minutes"), new Text("hours"), new Text("days")); 
    @Override
    public void start(Stage stage) throws Exception 
    {
        ComboBox<Text> cb = new ComboBox<Text>();
        for(int j = 0; j < SAMPUNITFRONT.size(); j++) // cycle over the list and generate a line with dashing defined by list
            {
                Text text = SAMPUNITFRONT.get(j);
                if(text.getText().equals("complete"))
                    text.setStyle("-fx-text-fill: RED");
                else
                    text.setStyle("-fx-text-fill: BLACK");
                cb.getItems().add(text);
            }

        cb.setCellFactory(new Callback<ListView<Text>, ListCell<Text>>() 
        {
            @Override public ListCell<Text> call(ListView<Text> p) 
            {
                return new ListCell<Text>() 
                {
                    private final Text text;
                        { 
                            setContentDisplay(ContentDisplay.GRAPHIC_ONLY); 
                            text = new Text();
                        } // end Text
                    @Override protected void updateItem(Text item, boolean empty) 
                        {   
                            super.updateItem(item, empty);
                            if (item == null || empty) 
                                {   
                                    setGraphic(null);
                                }
                            else 
                                {
                                    text.setStyle(item.getStyle());
                                    setGraphic(text); 
                                    setItem(text);
                                }
                        }  // end updateItem()
                }; // end ListCell return
            }
        });

        cb.getSelectionModel().selectFirst();
        Pane root = new Pane();
        root.getChildren().add(cb);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
    public static void main(String[] args) {launch(args);}
}

目前,组合的下拉列表为空。

【问题讨论】:

标签: java javafx combobox


【解决方案1】:

这里有几点建议:

  • 不要使用Node 类型作为项目类型。而是存储确定项目中ListCell 外观所需的数据,并让ListCell 实现处理其余部分。您可以简单地使用 String 作为项目类型,如果您应该仅根据文本或索引进行着色,或者您可以创建一个包含 2 个属性的类。
  • 不要自己打电话给setItem。让ComboBox/ListView 处理这个问题。
  • 对于Text,您需要使用-fx-fill css 属性而不是-fx-text-fill。如果您使用 ListCell 本身的 text 属性,后一种方法会起作用。
  • 如果你不使用ObservableList的功能,创建一个是没有意义的。您可以简单地使用ListArrays.asList 而不是ObservableListFXCollections.observableArrayList 用于SAMPUNITFRONT
final ObservableList<String> SAMPUNITFRONT = FXCollections.observableArrayList("complete",
        "seconds", "minutes", "hours", "days");

@Override
public void start(Stage stage) throws Exception {
    ComboBox<String> cb = new ComboBox<String>(SAMPUNITFRONT);

    cb.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
        @Override
        public ListCell<String> call(ListView<String> p) {
            return new ListCell<String>() {
                private final Text text;

                {
                    setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                    text = new Text();
                }

                @Override
                protected void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item == null || empty) {
                        setGraphic(null);
                    } else {
                        text.setStyle(item.equals("complete") ? "-fx-fill: red" : "-fx-fill: black");
                        text.setText(item);
                        setGraphic(text);
                    }
                }
            };
        }
    });

    cb.getSelectionModel().selectFirst();
    Pane root = new Pane();
    root.getChildren().add(cb);
    Scene scene = new Scene(root);
    stage.setScene(scene);
    stage.show();
}

或者不使用Text 作为graphic

return new ListCell<String>() {

    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);
        setText(item);
        if (item != null) {
            setStyle(item.equals("complete") ? "-fx-text-fill: red" : "-fx-text-fill: black");
        }
    }
};

【讨论】:

    【解决方案2】:

    问题是您将样式设置为 Text 对象。尝试为单元格设置相同的样式。而且您不需要将字符串封装在文本中。 这是您的修复代码:

    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.scene.Scene;
    import javafx.scene.control.ComboBox;
    import javafx.scene.control.ListCell;
    import javafx.scene.layout.Pane;
    import javafx.stage.Stage;
    
    public class Main extends Application
    {
        final ObservableList<String> SAMPUNITFRONT = FXCollections.observableArrayList("complete", "seconds", "minutes", "hours", "days");
    
        @Override
        public void start(Stage stage)
        {
            ComboBox<String> cb = new ComboBox<>();
    
            cb.setCellFactory(cell -> new ListCell<String>()
            {
                @Override
                protected void updateItem(String item, boolean empty)
                {
                    super.updateItem(item, empty);
                    if (item == null || empty)
                    {
                        setGraphic(null);
                        setText("");
                    }
                    else
                    {
                        if (item.equals("complete"))
                        {
                            setStyle("-fx-text-fill: RED");
                        }
                        setText(item);
                    }
                }
            });
    
    
            cb.getItems().addAll(SAMPUNITFRONT);
            cb.getSelectionModel().selectFirst();
            Pane root = new Pane();
            root.getChildren().add(cb);
            Scene scene = new Scene(root);
            stage.setScene(scene);
            stage.show();
        }
    
        public static void main(String[] args)
        {
            launch(args);
        }
    }
    

    结果:

    我希望我能正确理解您并能提供帮助。

    【讨论】:

    • 尝试使用比ListView 更多的项目,然后滚动...
    • 是的,大列表会出错。在这种情况下,可以使用 Text 或 Label 作为项目,并在设置其后将样式设置为单元工厂之外。像这样:cb.getItems().get(0).setStyle("-fx-text-fill: RED");
    • 感谢所有回复的人。我发现这里讨论的类似问题>java2s.com/Code/Java/JavaFX/…
    • 我在列表中获得了以红色显示的提名项目。现在我的问题是如何在组合框中选择提名项目“完成”后以红色显示,因为现在它显示为黑色。我附加了一个监听器,我知道我可以交换 CSS,但我正在寻找更简单的东西。如果 Hellomr 提供的语法可以工作, cb.getItems().get(0).setStyle("-fx-text-fill: RED");这会很棒,我可以将它添加到侦听器中,但事实并非如此。 .setStyle("-fx-text-fill: BLACK");确实有效。有什么想法吗?
    • @bocristi 您可能还没有设置使用与cellValueFactory 相同的ListCell 实现的buttonCell...
    猜你喜欢
    • 1970-01-01
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 2014-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多