JavaFX - 检测&突出显示正在拖动的TableColumn [英] JavaFX - Detect & highlight TableColumn being dragged onto

查看:151
本文介绍了JavaFX - 检测&突出显示正在拖动的TableColumn的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

发现哪个TableColumn(在TableView中)发生了DragEvent的最佳方法是什么?

What's the best way to discover which TableColumn (in a TableView) that a DragEvent occurred?

我希望能够突出显示(例如,将背景颜色更改为黄色,或在列周围显示黄色边框)TableColumn作为拖动项目是悬停在它上面,向用户清楚地告诉他们哪一列。拖动完成后,我必须确保恢复TableView的样式。

I'd like to be able to highlight (ex. change the background color to yellow, or show a yellow border around the column) a TableColumn as a dragged item is "hovering" over the it, to make it clear to the user which column they're dropping onto. After the drag is finished of course I'll have to make sure the TableView's style is restored.

要明确的是,确切的单元格被放置并不重要 - 只需要列。

To be clear, the exact cell being dropped onto doesn't matter - just the column.

推荐答案

要执行此操作,您需要向每个单元格注册拖动侦听器,以便在拖动单元格时使列更新其样式。我会使用 ObjectProperty 来表示当前的放置目标列(即正在进行拖动的列),并观察它并从单元格中更新它。要访问单元格,您需要一个单元工厂。

To do this, you need to register drag listeners with each cell that cause the column to update its style when the cells are dragged over. I would do this using an ObjectProperty to represent the current "drop target column" (i.e. column over which dragging is occurring), and both observe it and update it from the cells. To access the cells, you need a cell factory.

以下方法将为列添加此类支持。它还尊重先前附加的单元工厂中定义的任何功能:

The following method will add such support to a column. It also respects any functionality defined in a previously-attached cell factory:

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:

Here's a SSCCE using the usual "contact table" example:

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

这篇关于JavaFX - 检测&amp;突出显示正在拖动的TableColumn的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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