我正在尝试将自己构建的应用程序过渡到JavaFx。这包括全面检查GUI设计。该应用程序按以下方式处理数据:

从数据库中检索数据。数据库中的每一行都被解析为一个Java bean,并且每个bean被添加到一个ArrayList中。数组列表然后返回到调用方法,然后解析为ObservableList以使其与JavaFX tableview兼容。然后,通过向其中添加每个List元素(这是一个Java bean)来填充表。

值得注意的是,构成表的每一行的Java bean具有12个元素。该表在其9列中仅向用户显示其中的9个。我正在尝试执行的操作在行List元素中采用其他未显示的值之一,并使用它来确定所显示行的文本颜色设置为红色还是绿色。我似乎无法解决这个问题。我已经在Stack和其他论坛上查看了其他几个类似的问题,它们似乎解决了为特定单元格或列设置行文本颜色而不是为行设置问题。他们似乎也依靠可见的显示值来执行此操作。我尝试了几种方法,但是它们似乎都不起作用,而且看起来很复杂。对于我要尝试的操作,必须有一种更为直接的方法,因为这必须是一个相当普遍的要求。有人可以告诉我该怎么做吗?

我的表在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));
        }


我的另一个想法是使用lambda处理表行的内容,但是我仍然可以看到我如何获得实际的行。逐个单元设置每个元素似乎很麻烦,因此必须采用一种完全不同的方式来思考我没有想到的问题。如果有人可以解释并告诉我该怎么做,我将不胜感激。

最佳答案

代码示例,希望对您的情况有所帮助:

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


输出屏幕:

java - 根据用于填充表格的List元素中未显示的Java bean值设置JavaFX FXML表格行文本颜色-LMLPHP

Java Doc对其工作方式的解释:


  setRowFactory:
  
  产生TableRow的函数。系统负责
  重用TableRows。从此函数返回一个TableRow,它可能是
  可用于表示TableView中的单行。请注意
  TableRow不是TableCell。 TableRow只是一个容器
  对于TableCell,在大多数情况下,
  您将要创建自定义TableCell,而不是TableRows。的
  创建自定义TableRow实例的主要用例将是
  可能是要引入某种形式的列跨度支持。您
  可以通过分配以下内容来为每列创建自定义TableCell实例:
  TableColumn中cellFactory属性的适当函数
  类。 @return rowFactory属性


并为行中的每个单元格调用updateItem:


  updateItem:
  
  开发人员不应调用updateItem方法,但应使用
  开发人员重写的最佳方法,以允许他们
  自定义单元的外观。要澄清的是,开发人员永远不要
  在其代码中调用此方法(应将其留给用户界面
  控件(如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)方法。如果不这样做,则该项目和
  空属性设置不正确,很可能会导致失败
  图形问题。我们测试是否为空,如果为真,
  我们将文字和图形属性设置为null。如果我们不这样做,
  几乎可以保证最终用户将在
  细胞出乎意料。覆盖:类Cell Params中的updateItem:数据–
  单元格的新项目。空-此单元格是否代表
  列表中的数据。如果为空,则不代表任何
  域数据,但它是用于呈现“空”行的单元格。

关于java - 根据用于填充表格的List元素中未显示的Java bean值设置JavaFX FXML表格行文本颜色,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52686756/

10-10 14:10