发现DragEvent发生在哪个TableColumn(在TableView中)的最佳方法是什么?
我希望能够突出显示(例如,将背景颜色更改为黄色,或在列周围显示黄色边框)TableColumn,因为拖动的项目“悬停”在其上方,以便于用户清楚他们正在放的专栏。拖动完成后,我当然必须确保TableView的样式已恢复。
需要明确的是,确切的单元格没有关系-只是列。
为此,您需要在每个单元格中注册拖动侦听器,这会导致在单元格被拖动时该列更新其样式。我将使用ObjectProperty来代表当前的“放置目标列”(即在其上发生拖动的列)来进行此操作,并观察它并从单元格中对其进行更新。要访问单元,您需要一个单元工厂。
ObjectProperty
下面的方法会将这种支持添加到列中。它还尊重先前连接的单元工厂中定义的任何功能:
private <S,T> void configureDropTargetColumn(TableColumn<S,T> column, ObjectProperty<TableColumn<?,?>> dropTarget) { Callback<TableColumn<S,T>, TableCell<S,T>> currentCellFactory = column.getCellFactory() ; column.setCellFactory(tc -> { TableCell<S,T> cell = currentCellFactory.call(tc); dropTarget.addListener((obs, oldColumn, newColumn) -> cell.pseudoClassStateChanged(PseudoClass.getPseudoClass("drop-target"), newColumn==column)); cell.setOnDragEntered(e -> dropTarget.set(column)); cell.setOnDragExited(e -> dropTarget.set(null)); return cell ; }); }
这是使用通常的“联系表”示例的SSCCE:
import java.util.Arrays; import java.util.List; import java.util.function.Function; import javafx.application.Application; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; import javafx.css.PseudoClass; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.input.ClipboardContent; import javafx.scene.input.Dragboard; import javafx.scene.input.TransferMode; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; import javafx.util.Callback; public class TableColumnDropTargetExample extends Application { @Override public void start(Stage primaryStage) { TableView<Person> table = new TableView<>(); table.getColumns().add(column("First Name", Person::firstNameProperty)); table.getColumns().add(column("Last Name", Person::lastNameProperty)); table.getColumns().add(column("Email", Person::emailProperty)); ObjectProperty<TableColumn<?,?>> dropTargetColumn = new SimpleObjectProperty<>(); table.getColumns().forEach(col -> configureDropTargetColumn(col, dropTargetColumn)); table.getItems().addAll(createData()); Label label = new Label("Drag me"); label.getStyleClass().add("drag-source"); label.setOnDragDetected(e -> { Dragboard db = label.startDragAndDrop(TransferMode.COPY_OR_MOVE); ClipboardContent cc = new ClipboardContent(); cc.putString(label.getText()); db.setContent(cc); }); label.setOnDragDone(e -> dropTargetColumn.set(null)); BorderPane root = new BorderPane(table); root.setTop(label); BorderPane.setAlignment(label, Pos.CENTER); Scene scene = new Scene(root, 800, 600); scene.getStylesheets().add("style.css"); primaryStage.setScene(scene); primaryStage.show(); } private <S,T> void configureDropTargetColumn(TableColumn<S,T> column, ObjectProperty<TableColumn<?,?>> dropTarget) { Callback<TableColumn<S,T>, TableCell<S,T>> currentCellFactory = column.getCellFactory() ; column.setCellFactory(tc -> { TableCell<S,T> cell = currentCellFactory.call(tc); dropTarget.addListener((obs, oldColumn, newColumn) -> cell.pseudoClassStateChanged(PseudoClass.getPseudoClass("drop-target"), newColumn==column)); cell.setOnDragEntered(e -> dropTarget.set(column)); cell.setOnDragExited(e -> dropTarget.set(null)); return cell ; }); } private static <S,T> TableColumn<S,T> column(String text, Function<S, ObservableValue<T>> property) { TableColumn<S,T> col = new TableColumn<>(text); col.setCellValueFactory(cellData -> property.apply(cellData.getValue())); return col ; } private List<Person> createData() { return Arrays.asList( new Person("Jacob", "Smith", "jacob.smith@example.com"), new Person("Isabella", "Johnson", "isabella.johnson@example.com"), new Person("Ethan", "Williams", "ethan.williams@example.com"), new Person("Emma", "Jones", "emma.jones@example.com"), new Person("Michael", "Brown", "michael.brown@example.com") ); } public static class Person { private final StringProperty firstName = new SimpleStringProperty(); private final StringProperty lastName = new SimpleStringProperty(); private final StringProperty email = new SimpleStringProperty(); public Person(String firstName, String lastName, String email) { setFirstName(firstName); setLastName(lastName); setEmail(email); } public final StringProperty firstNameProperty() { return this.firstName; } public final String getFirstName() { return this.firstNameProperty().get(); } public final void setFirstName(final String firstName) { this.firstNameProperty().set(firstName); } public final StringProperty lastNameProperty() { return this.lastName; } public final String getLastName() { return this.lastNameProperty().get(); } public final void setLastName(final String lastName) { this.lastNameProperty().set(lastName); } public final StringProperty emailProperty() { return this.email; } public final String getEmail() { return this.emailProperty().get(); } public final void setEmail(final String email) { this.emailProperty().set(email); } } public static void main(String[] args) { launch(args); } }
和样式表:
.table-cell:drop-target { -fx-background-color: -fx-background ; -fx-background: yellow ; -fx-border-color: -fx-table-cell-border-color -fx-table-cell-border-color transparent transparent ; } .drag-source { -fx-font-size: 18 ; -fx-padding: 10 ; }