使用在任何列中都不可见的属性来更改表行颜色 [英] Changing table row color using a property that would not be visible in any column

查看:57
本文介绍了使用在任何列中都不可见的属性来更改表行颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用在tableview的任何列中都不可见的属性来更改表行的颜色.我做了以下事情:

I need to change the table row color using a property that would not be visible in any column of a tableview. I did the following:

  1. 创建模型类Person(serialNumberfirstlast).
  2. 使用提取器创建Person的observableList.
  3. 创建两个表视图(tableview1tableview2)和一个listview,它们都共享相同的数据.
  4. tableview1具有serialCol1列,其可见属性设置为 错误.
  1. create a model class Person (serialNumber, first, last).
  2. create an observableList of Person using an extractor.
  3. create two tableviews(tableview1, tableview2) and one listview that all sharing the same data.
  4. tableview1 has a serialCol1 column with a visible property set to false.

我想使用绑定到tableview2中列的serialNumber属性更改tableview1行颜色.

I want to change tableview1 row color using the serialNumber property that is bound to a column in a tableview2.

这是完整的程序:

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;

/**
 *
 * @author kachna
 */
public class Extractor extends Application {

    private final TableView<Person> tableView1 = new TableView<>();
    private final TableView<Person> tableView2 = new TableView<>();
    private final ListView<Person> listView = new ListView<>();
    //observable list with extractor
    private final ObservableList<Person> data = FXCollections.observableArrayList(p -> new Observable[]{p.serialNumberProperty(), p.firstProperty(), p.lastProperty()});

    static class Person {

        final IntegerProperty serialNumber;
        final StringProperty first;
        final StringProperty last;

        public Person(int serialNumber, String first, String last) {
            this.first = new SimpleStringProperty(first);
            this.last = new SimpleStringProperty(last);
            this.serialNumber = new SimpleIntegerProperty(serialNumber);
        }

        public IntegerProperty serialNumberProperty() {
            return serialNumber;
        }

        public StringProperty firstProperty() {
            return first;
        }

        public StringProperty lastProperty() {
            return last;
        }

        @Override
        public String toString() {
            return "Person{" + "first=" + first.get() + ", last=" + last.get() + '}';
        }

    }

    @Override
    public void start(Stage stage) {

        BorderPane root = new BorderPane();
        VBox vBox = new VBox(10);
        VBox.setVgrow(tableView2, Priority.ALWAYS);
        root.setPadding(new Insets(10));
        initTableViews();
        initListView();
        getData();
        Label label1 = new Label("TableView 1");
        label1.setStyle("-fx-font-size: 24px;\n"
                + "-fx-font-weight: bold;");
        Label label2 = new Label("TableView 2");
        label2.setStyle("-fx-font-size: 24px;\n"
                + "-fx-font-weight: bold;");
        vBox.getChildren().addAll(label1, tableView1,label2, tableView2);
        root.setCenter(vBox);
        root.setRight(listView);
        Scene scene = new Scene(root, 600, 400);
        stage.setScene(scene);
        stage.show();

    }

    private void initTableViews() {
        // first table view 
        tableView1.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        tableView1.setEditable(true);
        tableView1.setRowFactory(tv -> new TableRow<Person>() {

            @Override
            protected void updateItem(Person item, boolean empty) {
                super.updateItem(item, empty);
                if (item != null) {
                    if (item.serialNumber.get() % 2 == 0) {
                        setStyle("-fx-background-color: orange;");
                    } else {
                        setStyle(" ");
                    }
                } else {
                    setStyle(" ");
                }
            }

        });

        TableColumn<Person, Number> serialCol1 = new TableColumn<>("Serial Number");
        serialCol1.setCellValueFactory(cellData -> cellData.getValue().serialNumberProperty());
        serialCol1.setCellFactory(TextFieldTableCell.forTableColumn(new StringConverter<Number>() {

            @Override
            public String toString(Number object) {
                return object.toString();
            }

            @Override
            public Number fromString(String string) {
                return Integer.parseInt(string);
            }
        }));

        // make the serialCol1 column invisible
        serialCol1.setVisible(false);
        TableColumn<Person, String> firstCol1 = new TableColumn<>("First Name");
        firstCol1.setCellValueFactory(cellData -> cellData.getValue().firstProperty());
        firstCol1.setCellFactory(TextFieldTableCell.forTableColumn());
        TableColumn<Person, String> lastCol1 = new TableColumn<>("Last Name");
        lastCol1.setCellFactory(TextFieldTableCell.forTableColumn());
        lastCol1.setCellValueFactory(cellData -> cellData.getValue().lastProperty());
        tableView1.getColumns().addAll(serialCol1, firstCol1, lastCol1);
        tableView1.setItems(data);

        // second table view  
        tableView2.setEditable(true);
        tableView2.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        TableColumn<Person, Number> serialCol = new TableColumn<>("Serial Number");
        serialCol.setCellValueFactory(cellData -> cellData.getValue().serialNumberProperty());
        serialCol.setCellFactory(TextFieldTableCell.forTableColumn(new StringConverter<Number>() {

            @Override
            public String toString(Number object) {
                return object.toString();
            }

            @Override
            public Number fromString(String string) {
                return Integer.parseInt(string);
            }
        }));
        TableColumn<Person, String> firstCol2 = new TableColumn<>("First Name");
        firstCol2.setCellValueFactory(cellData -> cellData.getValue().firstProperty());
        TableColumn<Person, String> lastCol2 = new TableColumn<>("Last Name");
        lastCol2.setCellFactory(TextFieldTableCell.forTableColumn());
        lastCol2.setCellValueFactory(cellData -> cellData.getValue().lastProperty());
        tableView2.getColumns().addAll(serialCol, firstCol2, lastCol2);
        tableView2.setItems(data);
    }

    private void initListView() {
        //list view 

        listView.setCellFactory(list -> new ListCell<Person>() {
            @Override
            protected void updateItem(Person value, boolean empty) {
                super.updateItem(value, empty);
                if (!empty && value != null) {
                    if (value.serialNumber.get() % 2 == 0) {
                        setStyle("-fx-background-color: orange;");
                    } else {
                        setStyle(" ");
                    }
                    setText(String.format("%s %s %s", value.serialNumber.get(), value.firstProperty().get(), value.lastProperty().get()));
                } else {
                    setText(null);
                    setStyle(" ");
                }

            }
        });

        listView.setItems(data);
    }

    private void getData() {
        data.setAll(IntStream.range(0, 10)
                .mapToObj(i -> new Person(i, "first" + i, "last" + i))
                .collect(Collectors.toList()));
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

问题:

  • tableview1的样式在应用 改变.我必须滚动浏览各行才能看到样式更新. listview的样式立即更改,没有任何问题.
  • the style of tableview1 doesn't change instantly after applying a change. I have to scroll hrough the rows to see the style updated. the style of the listview is changed instantly without any problems.

推荐答案

updateItem方法未绑定到其项的属性生命周期(项不得为Observable),而是由View调用( ListView/TableView),只要它认为有必要更新数据表示形式即可.在屏幕上滚动行时,该行将为空(出于性能原因,我认为是),并在屏幕上再次更新.

The updateItem method is not bound to the property lifecycle of its item ( an item must not be an Observable ), but rather gets called by the View (ListView/TableView) whenever it deems it necessary to update the data representation. When you scroll a Row off screen it gets nulled ( I assume for performance reasons ) and updated again when in screen.

您要执行的操作是将行的styleProperty绑定到其项serialNumberProperty,如下所示:

What you want to do is to bind the stylePropertyof the row to its items serialNumberPropertylike so:

tableView1.setRowFactory( tv -> new TableRow<Person>()
    {
      @Override
      protected void updateItem( final Person item, final boolean empty )
      {
        super.updateItem( item, empty );

        if ( !empty && item != null )
        {

          this.styleProperty().bind( Bindings.createStringBinding( () ->
          {
            if ( item.serialNumber.get() % 2 == 0 )
            {
              return "-fx-background-color: orange;";
            }
            return " ";
          } , item.serialNumberProperty() ) );

        }
        else
        {
          /*
           * As per comment in the Cell API
           */
          setText( null );
          setGraphic( null );

          this.styleProperty().unbind();

          setStyle( " " );
        }
      }
    } );

我还建议查阅javafx.scene.control.Cell#updateitem(...)的文档,因为它被标记为专家API".

I also recommend consulting the documentation of javafx.scene.control.Cell#updateitem(...) as it is marked as "Expert API".

链接到完整示例.

这篇关于使用在任何列中都不可见的属性来更改表行颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆