Текстовое поле со списком фабричного вызова - PullRequest
1 голос
/ 06 июня 2019

Для моего проекта в Java FX у меня есть список строк, и мне нужно добавить их в поле со списком с требованием, чтобы только одна из них (первая) была окрашена в красный цвет.

Я думал об инкапсуляции строк в тексте и добавлении их в поле со списком с помощью соответствующего 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);}
}

В данный момент раскрывающийся список со списком пуст.

Ответы [ 2 ]

2 голосов
/ 06 июня 2019

Несколько рекомендаций, которые следует сделать здесь:

  • Не используйте тип Node в качестве типа элемента.Вместо этого сохраните данные, необходимые для определения вида ListCell в элементах, и пусть реализации ListCell справятся с остальными.Вы можете просто использовать String в качестве типа элемента, если окраска должна выполняться только на основе текста или индекса, или вы можете создать класс, содержащий 2 свойства.
  • Не вызывайте setItem самостоятельно.Пусть ComboBox / ListView справится с этим.
  • Для Text вам нужно использовать свойство -fx-fill css вместо -fx-text-fill.Последнее будет работать, если вы используете свойство text самого ListCell.
  • Если вы не используете функциональность ObservableList, создавать его бессмысленно.Вы могли бы просто использовать List и Arrays.asList вместо ObservableList и FXCollections.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");
        }
    }
};
0 голосов
/ 06 июня 2019

Проблема в том, что вы устанавливаете стиль для текстовых объектов.Попробуйте установить тот же стиль для клеток.И вам не нужно инкапсулировать строки в текст.Вот ваш код с исправлениями:

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);
    }
}

И результат:

enter image description here

Надеюсь, я вас правильно понял и смог помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...