TableRow样式按条件更改

时间:2016-10-12 13:48:39

标签: java javafx tableview

有两个表:

@FXML
TableView<FrameGroupIntersections> tvOldGroups;
@FXML
TableView<FrameGroupIntersections> tvNewGroups;

enter image description here

这些链接在课堂上:

public class FrameGroupIntersections {

    private FrameGroup group;

    private ObservableMap<FrameGroupIntersections,IntTypeInfoWrapper> intersections;

    private BooleanProperty hasErr;

    FrameGroupIntersections (FrameGroup group, Map<FrameGroupIntersections,IntTypeInfoWrapper> intersections){
        this.group = group;
        hasErr = new SimpleBooleanProperty(false);
        setIntersections(intersections);
    }

    FrameGroupIntersections(FrameGroup group){
        this(group,null);
    }
    //Other methods
}

即。左表中的FrameGroupIntersections包含FrameGroupIntersections地图右表中intersections的链接。反过来也是如此。

当控制器初始化时,我收到两个ObservableList为&#34; old&#34;和&#34;新&#34;。

class Controller {
    //FXML nodes
    //Lists of intersections
    ObservableList<FrameGroupIntersections> oFgInt;
    ObservableList<FrameGroupIntersections> nFgInt;

    public void init(MergeReportDataWrapper dataWrapper){
        this.oFgInt = dataWrapper.getoFgInt();
        this.nFgInt = dataWrapper.getnFgInt();
        //Data binding
    }
}

该列表中的所有交叉点均已链接。

当在两个表中选择一些FrameGroupIntersections时,有必要从其他表中链接FrameGroupIntersections行来改变自己的背景。请告诉我如何做到这一点?

1 个答案:

答案 0 :(得分:2)

我仍然不能100%确定如何确定是否需要在另一个TableView中选择某个项目,所以我创建了一些示例,只需使用Map来映射该项目到要从另一个表中选择的对象列表。

Item<T>只是一个value属性包含T类型对象的类:

@Override
public void start(Stage primaryStage) {
    // create data
    ObservableList<Item<String>> data1 = FXCollections.observableArrayList(
            new Item("A"),
            new Item("B"),
            new Item("C"),
            new Item("D")
    );
    ObservableList<Item<String>> data2 = FXCollections.observableArrayList(
            new Item("A"),
            new Item("B"),
            new Item("C"),
            new Item("D")
    );

    // create tableview & columns
    TableView<Item<String>> table1 = new TableView<>(data1);
    TableView<Item<String>> table2 = new TableView<>(data2);

    TableColumn<Item<String>, String> column1 = new TableColumn<>();
    column1.setCellValueFactory(new PropertyValueFactory("value"));

    TableColumn<Item<String>, String> column2 = new TableColumn<>();
    column2.setCellValueFactory(new PropertyValueFactory("value"));

    table1.getColumns().add(column1);
    table2.getColumns().add(column2);

    // create maps mapping values to values to select in the other table,
    // should a item be selected
    Map<Item<String>, List<Item<String>>> selection1To2 = new HashMap<>();
    selection1To2.put(data1.get(0), Arrays.asList(data2.get(0), data2.get(1)));
    selection1To2.put(data1.get(2), Arrays.asList(data2.get(1), data2.get(2)));

    Map<Item<String>, List<Item<String>>> selection2To1 = new HashMap<>();
    selection2To1.put(data2.get(1), Arrays.asList(data1.get(2), data1.get(3)));
    selection2To1.put(data2.get(3), Arrays.asList(data1.get(0), data1.get(1), data1.get(2), data1.get(3)));

    // sets of items to select depending on table selections
    ObservableSet<Item<String>> otherSelections1 = connect(table2, selection2To1);
    ObservableSet<Item<String>> otherSelections2 = connect(table1, selection1To2);

    // assign row factories for assigning pseudoclasses
    table1.setRowFactory(new RowFactory(otherSelections1));
    table2.setRowFactory(new RowFactory(otherSelections2));

    Scene scene = new Scene(new HBox(10, table1, table2));
    scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());

    primaryStage.setScene(scene);
    primaryStage.show();
}

private static <T> ObservableSet<T> connect(TableView<T> table, Map<T, List<T>> map) {
    ObservableSet<T> result = FXCollections.observableSet(new HashSet<>());

    // keep set elements the union of the list elements for the items selected in the table
    table.getSelectionModel().getSelectedItems().addListener((Observable o) -> {
        result.clear();
        for (T item : table.getSelectionModel().getSelectedItems()) {
            List<T> itemsToAdd = map.get(item);
            if (itemsToAdd != null) {
                result.addAll(itemsToAdd);
            }
        }
    });
    return result;
}

private static final PseudoClass OTHER_SELECTED = PseudoClass.getPseudoClass("other-selected");

private static class RowFactory implements Callback<TableView<Item<String>>, TableRow<Item<String>>> {

    private final ObservableSet<Item<String>> selected;

    public RowFactory(ObservableSet<Item<String>> selected) {
        this.selected = selected;
    }

    @Override
    public TableRow<Item<String>> call(TableView<Item<String>> param) {
        // rows contain pseudoclass depending on other selection
        return new TableRow<Item<String>>() {

            {
                selected.addListener((Observable o) -> updateOtherSelected());
            }

            @Override
            protected void updateItem(Item<String> item, boolean empty) {
                super.updateItem(item, empty);
                updateOtherSelected();
            }

            private void updateOtherSelected() {
                pseudoClassStateChanged(OTHER_SELECTED, selected.contains(getItem()));
            }

        };
    }

}

的style.css

.table-row-cell:other-selected {
    -fx-background: orange;
}

.table-row-cell:other-selected:selected {
    -fx-background: purple;
}