当setCellSelectionEnabled(true)时,从JavaFX中的TableView中的选定单元格中获取行

时间:2016-11-03 21:23:26

标签: tableview javafx-8

我有以下代码,当我有标准行选择(总是单行,从不多)时,它可以很好地工作。

//This is needed to set the X & Y coordinates of the stage for edit.
myTable.setRowFactory(tableView -> {
     TableRow<MyDTO> row = new TableRow<MyDTO>();
          row.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
          if (isNowSelected) {
              lastSelectedRow.set(row);
          }
     });
     return row ;
});

我正在使用该行来获取父级的边界,这样当用户选择编辑该行时,我可以在该行下方弹出一个模态窗口,供他们编辑。

但是,我的表格也适用于没有需要查找等的常见字段。在这种情况下,我想在表格中进行编辑。所有这一切都有效,但为了使用户更友好,我希望打开单元格选择,但是当我这样做时,row.selectedProptery()监听器不会被激活。

如何在不尝试收听每个单元格的selectedProperty()的情况下实现这一目标?

由于

1 个答案:

答案 0 :(得分:1)

我认为没有办法在没有通过每个表格列上的单元工厂注册每个单元格的选择属性的侦听器的情况下执行此操作。

然而,这并不太困难,并且可以一般地完成(即,无论表列的类型使用相同的代码),还要尊重您需要的任何其他单元工厂行为。这是一个SSCCE:

import java.util.Random;
import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Callback;

public class SelectedTableCellTracking extends Application {

    private final ObjectProperty<TableCell<?,?>> selectedCell = new SimpleObjectProperty<>();

    @Override
    public void start(Stage primaryStage) {
        TableView<Item> table = new TableView<>();
        TableColumn<Item, String> itemCol = column("Item", Item::nameProperty);
        TableColumn<Item, Number> valueCol = column("Value", Item::valueProperty);
        table.getColumns().add(itemCol);
        table.getColumns().add(valueCol);

        Random rng = new Random();
        for (int i = 1 ; i <= 100; i++) {
            table.getItems().add(new Item("Item "+i, rng.nextInt(1000))); 
        }

        table.getSelectionModel().setCellSelectionEnabled(true);

        Rectangle highlight = new Rectangle();
        highlight.setManaged(false);
        highlight.setHeight(12);
        highlight.setFill(Color.CORAL);
        StackPane root = new StackPane(table, highlight);


        selectedCell.addListener((obs, oldCell, newCell) -> {
            if (newCell == null) {
                highlight.setVisible(false);
            } else {
                highlight.setVisible(true);
                highlight.setX(newCell.localToScene(newCell.getBoundsInLocal()).getMinX());
                highlight.setWidth(newCell.getWidth());
                highlight.setY(newCell.localToScene(newCell.getBoundsInLocal()).getMaxY());
            }

        });

        table.getColumns().forEach(this::addCellSelectionListenerToColumn);

        Scene scene = new Scene(root, 800, 800);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private <S,T> void addCellSelectionListenerToColumn(TableColumn<S,T> col) {
        Callback<TableColumn<S,T>, TableCell<S,T>> currentCellFactory = col.getCellFactory();
        col.setCellFactory(tc -> {
            TableCell<S,T> cell = currentCellFactory.call(tc);
            cell.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
                if (isNowSelected) {
                    selectedCell.set(cell);
                } 
            });
            return cell ;
        });
    }


    private static <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property) {
        TableColumn<S,T> col = new TableColumn<>(title);
        col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
        return col ;
    }

    public static class Item {
        private final StringProperty name = new SimpleStringProperty();
        private final IntegerProperty value = new SimpleIntegerProperty();

        public Item(String name, int value) {
            setName(name);
            setValue(value);
        }

        public final StringProperty nameProperty() {
            return this.name;
        }


        public final String getName() {
            return this.nameProperty().get();
        }


        public final void setName(final String name) {
            this.nameProperty().set(name);
        }


        public final IntegerProperty valueProperty() {
            return this.value;
        }


        public final int getValue() {
            return this.valueProperty().get();
        }


        public final void setValue(final int value) {
            this.valueProperty().set(value);
        }



    }

    public static void main(String[] args) {
        launch(args);
    }
}