为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

芜湖不芜 2021-11-03 14:44:09
我正在尝试将我在 Swing 中构建的应用程序转换为 JavaFx。这包括彻底检查 GUI 设计。应用程序处理数据如下:从数据库中检索数据。数据库中的每一行都被解析为一个 java bean,每个 bean 被添加到一个 ArrayList。然后将数组列表返回给调用方法,然后解析为 ObservableList 以使其与 JavaFX tableview 兼容。然后我通过向它添加每个 List 元素(它是一个 java bean)来填充该表。重要的是,构成表格每一行的 Java bean 有 12 个元素。该表在其 9 列中仅向用户显示其中的 9 个。我正在尝试使用行列表元素中其他未显示的值之一,并使用它来确定所显示行的文本颜色是设置为红色还是绿色。我似乎无法管理这个。我在 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>我的另一个想法是使用 lambda 来处理表格行内容,但我再次可以看到我是如何获得实际行的。逐个单元地设置每个元素似乎真的很复杂,所以必须有一种完全不同的方式来思考这个我没有得到的。如果有人可以解释并告诉我如何做到这一点,我将不胜感激。
查看完整描述

1 回答

?
森林海

TA贡献2011条经验 获得超2个赞

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


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

    }

}

输出画面:

//img1.sycdn.imooc.com//61822fdc0001aa4a02650457.jpg

Java Doc对其工作原理的解释:

设置行工厂:

产生 TableRow 的函数。系统负责重用TableRows。从此函数返回一个 TableRow,它可能可用于表示 TableView 中的单行。

请注意,TableRow不是TableCell。TableRow 只是 TableCell 的容器,在大多数情况下,您更有可能希望创建自定义 TableCell,而不是 TableRow。创建自定义 TableRow 实例的主要用例很可能是引入某种形式的列跨越支持。

您可以通过将适当的函数分配给 TableColumn 类中的 cellFactory 属性,为每列创建自定义 TableCell 实例。@return rowFactory 属性

以及对一行中每个单元格的 updateItem 调用:

更新项目:

updateItem 方法不应由开发人员调用,但它是开发人员重写以允许他们自定义单元格的视觉效果的最佳方法。澄清一下,开发人员永远不应该在他们的代码中调用这个方法(他们应该把它留给 UI 控件,比如 ListView 控件)来调用这个方法。但是,拥有 updateItem 方法的目的是让开发人员在指定自定义单元工厂(同样,如 ListView 单元工厂)时,可以覆盖 updateItem 方法以允许完全自定义单元。Cell 的子类正确覆盖 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 属性设置不正确,最终可能会出现图形问题。我们测试空条件,如果为真,我们将文本和图形属性设置为空。如果我们不这样做,几乎可以保证最终用户会意外地看到单元格中的图形工件。覆盖:单元格中的 updateItem 参数:数据 – 单元格的新项目。空 - 此单元格是否代表列表中的数据。如果它是空的,那么它不代表任何域数据,而是一个用于呈现“空”行的单元格。


查看完整回答
反对 回复 2021-11-03
  • 1 回答
  • 0 关注
  • 182 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信