Установите цвет текста строки таблицы JavaFX FXML на основе значения неотображаемого компонента Java в элементе списка, используемом для заполнения таблицы - PullRequest
0 голосов
/ 07 октября 2018

Я пытаюсь перевести приложение, созданное мной в Swing, на JavaFx.Это включает в себя капитальный ремонт дизайна GUI.Приложение обрабатывает данные следующим образом:

Данные извлекаются из базы данных.Каждая строка в базе данных анализируется на Java-бин, и каждый бин добавляется в ArrayList.Список массивов затем возвращается вызывающему методу, а затем анализируется в ObservableList, чтобы сделать его совместимым с табличным представлением JavaFX.Затем я заполняю таблицу, добавляя к ней каждый элемент списка - который является Java-бином.

Важно отметить, что Java-бин, составляющий каждую строку таблицы, имеет 12 элементов.Таблица отображает только 9 из них для пользователя в своих 9 столбцах.То, что я пытаюсь сделать, это взять одно из других неотображаемых значений в элементе List строк и использовать это, чтобы определить, установлен ли цвет текста отображаемой строки на красный или зеленый.Я не могу справиться с этим.Я рассмотрел несколько других похожих вопросов на стеке и других форумах, и они, кажется, решают проблему установки цвета текста ячейки для конкретной ячейки или столбца, но не для строки.Они также, кажется, делают это, полагаясь на видимое отображаемое значение.Я пробовал несколько подходов, но ни один из них не работает, и они кажутся сложными.Должен быть гораздо более прямой подход к тому, что я пытаюсь сделать, поскольку это должно быть довольно распространенным требованием.Может кто-нибудь показать мне, как это сделать?

Моя таблица определяется в FXML следующим образом:

 <TableView fx:id="toDoTable" editable="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
           <columns>
              <TableColumn fx:id="todoID" prefWidth="59.0" text="ID" />
              <TableColumn id="columnHeader" fx:id="Charity" prefWidth="77.0" text="Charity" />
              <TableColumn fx:id="todoFunder" prefWidth="101.0" text="Funder" />
              <TableColumn fx:id="todoType" prefWidth="92.0" text="Task Type" />
              <TableColumn fx:id="todoInternalDeadline" prefWidth="145.0" text="Internal Deadline" />
              <TableColumn fx:id="todoExternalDeadline" prefWidth="145.0" text="External Deadline" />
              <TableColumn fx:id="todoHrs" prefWidth="140.0" text="Target Hours" />
              <TableColumn fx:id="todoActualHrs" prefWidth="110.0" text="Actual Hours" />
              <TableColumn fx:id="todoDescription" prefWidth="110.0" text="Description" />
           </columns>
        </TableView>

Таблица заполняется в методе инициализации в соответствующем классе контроллера следующим образом:

public void initialize(URL url, ResourceBundle rb) {

    todoID.setCellValueFactory(new PropertyValueFactory<>("taskID"));
    todoClient.setCellValueFactory(new PropertyValueFactory<>("Charity"));
    todoFunder.setCellValueFactory(new PropertyValueFactory<>("taskFunder"));
    todoType.setCellValueFactory((new PropertyValueFactory<>("taskType")));
    todoInternalDeadline.setCellValueFactory((new PropertyValueFactory<>("internalDeadline")));
    todoExternalDeadline.setCellValueFactory((new PropertyValueFactory<>("externalDeadline")));
    todoHrs.setCellValueFactory((new PropertyValueFactory<>("assignedHours")));
    todoActualHrs.setCellValueFactory((new PropertyValueFactory<>("hoursCompleted")));
    todoDescription.setCellValueFactory((new PropertyValueFactory<>("taskDescription")));

    ObservableList<Task> list = FXCollections.observableArrayList(parseTaskBeans());//parseTaskBeans();
    toDoTable.getItems().addAll(list);
    GuiUtility.autoResizeColumns(toDoTable);
    //toDoTable.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
    toDoTable.autosize(); 
}

Хотя вышеприведенное заполняет всю таблицу, я думаю, что мне нужно сделать, это обработать строки по отдельности и покрасить их, прежде чем добавлять их в представление.Я предполагаю, что цвет должен быть свойством элемента таблицы, а не списка, поскольку список - это просто данные.Моя последняя попытка приведена ниже, но я думаю, что это должно быть совершенно неверно, так как я не могу найти способ получить текст в строке, чтобы определить его цвет.Поэтому я оставил комментарии там, где, как мне кажется, мне нужно добавить код для решения этой проблемы:

    for(int i = 0; i<list.size(); i++){
        System.out.println(list.get(i).getTaskReturned());
        if(list.get(i).getTaskReturned().equalsIgnoreCase("false")){
            //set Color red
        }
            else{
            //set color green
            }
            toDoTable.getItems().add(list.get(i));
        }

Еще одна мысль, которая у меня возникла, - использовать лямбду для обработки содержимого строки таблицы, но снова я вижу, как получитьв фактическом ряду.Кажется действительно сложным устанавливать каждый элемент ячейка за ячейкой, поэтому должен быть совершенно другой способ думать об этом, чего я не понимаю.Если бы кто-то мог объяснить и показать мне, как это сделать, я был бы признателен.

1 Ответ

0 голосов
/ 07 октября 2018

пример кода, надеюсь, он поможет вашему делу:

public class Main extends Application {
    private TableView table = new TableView();
    @Override
    public void start(Stage primaryStage) throws Exception{
        ObservableList<Data> data = FXCollections.observableArrayList(
                new Data("Jacob", "Smith", true),
                new Data("Isabella", "Johnson",true),
                new Data("Ethan", "Williams", false),
                new Data("Emma", "Jones", true),
                new Data("Michael", "Brown", true)
        );
        TableColumn firstDataCol = new TableColumn("Data1");
        firstDataCol.setMinWidth(100);
        firstDataCol.setCellValueFactory(
                new PropertyValueFactory<Data, String>("data1"));

        TableColumn secondDataCol = new TableColumn("Data2");
        secondDataCol.setMinWidth(100);
        secondDataCol.setCellValueFactory(
                new PropertyValueFactory<Data, String>("data2"));

        /*TableColumn isGreenCol = new TableColumn("IsGreen");
        isGreenCol.setMinWidth(200);
        isGreenCol.setCellValueFactory(
                new PropertyValueFactory<Data, Boolean>("isGreen"));*/

        table.setRowFactory(new Callback<TableView<Data>, TableRow<Data>>() {
            @Override
            public TableRow<Data> call(TableView<Data> tableView) {
                final TableRow<Data> row = new TableRow<Data>() {
                    @Override
                    protected void updateItem(Data data, boolean empty){
                        super.updateItem(data, empty);
                        if (data!=null&&data.isGreen.get()) {
                           setStyle("-fx-text-background-color: green;");

                        } else {
                            setStyle("-fx-text-background-color: red;");
                        }
                    }
                };

                return row;
            }
        });

        table.setItems(data);
        table.getColumns().addAll(firstDataCol, secondDataCol);
        Parent window = new VBox();
        ((VBox) window).getChildren().add(new Label("example of small window:"));
        primaryStage.setTitle("example");
        ((VBox) window).getChildren().add(table);
        Scene scene=new Scene(window);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public class Data {
        private final SimpleStringProperty data1;
        private final SimpleStringProperty data2;
        private final SimpleBooleanProperty isGreen;

        public Data(String data1, String data2, Boolean isGreen) {
            this.data1 = new SimpleStringProperty(data1);
            this.data2 = new SimpleStringProperty(data2);
            this.isGreen = new SimpleBooleanProperty(isGreen);
        }

        public String getData1() {
            return data1.get();
        }

        public SimpleStringProperty data1Property() {
            return data1;
        }

        public String getData2() {
            return data2.get();
        }

        public SimpleStringProperty data2Property() {
            return data2;
        }

        public boolean isIsGreen() {
            return isGreen.get();
        }

        public SimpleBooleanProperty isGreenProperty() {
            return isGreen;
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}

экран вывода:

enter image description here

объяснениео том, как это работает в Java. Doc:

setRowFactory:

Функция, которая создает TableRow.Система отвечает за повторное использование TableRows.Верните из этой функции TableRow, который может быть использован для представления одной строки в TableView.

Обратите внимание, что TableRow не TableCell.TableRow - это просто контейнер для TableCell, и в большинстве случаев более вероятно, что вы захотите создать пользовательские TableCell, а не TableRows.Основным вариантом использования для создания пользовательских экземпляров TableRow, скорее всего, будет введение некоторой формы поддержки расширения столбцов.

Вы можете создавать собственные экземпляры TableCell для каждого столбца, назначая соответствующую функцию свойству cellFactory в классе TableColumn.свойство @return rowFactory

и вызов updateItem для каждой ячейки в строке:

updateItem:

Метод updateItem не должен вызываться разработчиками, но это лучший способ для разработчиков переопределить, чтобы позволить им настраивать визуальные элементы ячейки.Чтобы уточнить, разработчики никогда не должны вызывать этот метод в своем коде (они должны оставить его на усмотрение элемента управления UI, такого как элемент управления ListView) для вызова этого метода.Однако цель использования метода updateItem заключается в том, чтобы при указании пользовательских фабрик ячеек (опять же, как фабрика ячеек ListView) разработчики могли переопределить метод updateItem, чтобы обеспечить полную настройку ячейки.Очень важно, чтобы подклассы Cell правильно переопределяли метод updateItem, так как в противном случае возникнут такие проблемы, как пустые ячейки или ячейки с неожиданным содержимым, появляющимся в них.Вот пример того, как правильно переопределить метод updateItem:

protected void updateItem(T item, boolean empty) {
            super.updateItem(item, empty);

            if (empty || item == null) {
                setText(null);
                setGraphic(null);
            } else {
                setText(item.toString());
            }
        }

Обратите внимание в этом примере кода на два важных момента: Мы вызываем метод super.updateItem (T, boolean).Если этого не сделать, свойства item и empty установлены неправильно, и вы, скорее всего, столкнетесь с графическими проблемами.Мы проверяем пустое условие, и если true, мы устанавливаем свойства текста и графики в null.Если мы этого не сделаем, почти гарантировано, что конечные пользователи увидят графические артефакты в ячейках неожиданно.Переопределяет: updateItem в классе Cell. Params: data - новый элемент для ячейки.пусто - представляет ли эта ячейка данные из списка.Если он пуст, он не представляет никаких данных домена, но является ячейкой, используемой для визуализации «пустой» строки.

...