JavaFX - 将一行从表格视图拖到文本区域中

Luk*_*Luk 1 drag-and-drop javafx tableview

考虑 JavaFX 应用程序内的表格视图。表视图包含有关人员的数据:

id    firstname    lastname

1     John         Doe
Run Code Online (Sandbox Code Playgroud)

表视图的每一行都可以用来实例化一个 Person 对象:

new Person(Integer id, String firstname, String lastname)

这是我想做的:

我想选择表格视图中的一个人,然后用鼠标将其拖动到文本区域中。在文本区域内我想打印字符串:

1 John Doe

我知道我必须实现三个函数才能实现此目的:onDragDetected(), onDragOver() and onDragDropped()

我想从以下开始:

public void onDragDetected(DragEvent dragevent) {
    Person person = tvPersonData.getSelectionModel().getSelectedItem();
}
Run Code Online (Sandbox Code Playgroud)

这有效。但我必须以某种方式让我的 Person 进入 DragBoard 对象 ( dragevent.getDragboard())。我想我是这样的。然后也许我的其他功能可以使用我的拖板内的任何内容。

有人可以帮我从这里出去吗?

Zep*_*hyr 5

为了在手势中使用自定义对象,您需要为该对象DragAndDrop定义一个自定义:DataFormat

DataFormat personDataFormat = new DataFormat("com.package.Person");
Run Code Online (Sandbox Code Playgroud)

显然,您需要将其替换com.package.Person为您为其创建的类的完整路径。

另请注意,为了将某个类用作 a DataFormat,该类必须是Serializable。这是通过SerializablePerson对象中实现接口来完成的:

class Person implements Serializable {}
Run Code Online (Sandbox Code Playgroud)

另一件要记住的事情是,JavaFX 属性并非Serializable如此,如果您StringPropertyPerson对象中使用,这将不起作用;您需要创建一个包装类来保存您需要的数据。


一旦您完成DataFormatPerson实现了Serializable,您就可以Person像任何其他内容一样将对象复制到剪贴板;你只需要DataFormat为其指定:

ClipboardContent content = new ClipboardContent();
content.put(personDataFormat, tableView.getSelectionModel().getSelectedItem());
Run Code Online (Sandbox Code Playgroud)

下降到 上TextArea将会是类似的。您将定义DataFormat并添加代码以根据需要进行处理:

Person droppedPerson = (Person) db.getContent(personDataFormat);
textArea.appendText(droppedPerson.getName() + "\n");
Run Code Online (Sandbox Code Playgroud)

完整的示例应用程序如下:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.Serializable;
import java.util.Arrays;

public class DragObject extends Application {

    private final TableView<Person> tableView = new TableView<>();
    private final TextArea textArea = new TextArea();

    public static void main(String[] args) {

        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        // **********************************************************************************************
        // Create a basic layout
        // **********************************************************************************************
        VBox root = new VBox(5);
        root.setAlignment(Pos.TOP_CENTER);
        root.setPadding(new Insets(10));

        // **********************************************************************************************
        // Configure a regular TableView
        // **********************************************************************************************
        configureTableView();

        tableView.setItems(sampleData());
        tableView.setPrefHeight(200);
        root.getChildren().add(tableView);

        root.getChildren().add(textArea);

        // **********************************************************************************************
        // This method will configure our drag-and-drop functionality
        // **********************************************************************************************
        initDragAndDrop();

        // **********************************************************************************************
        // Set the Scene for the stage
        // **********************************************************************************************
        primaryStage.setScene(new Scene(root));

        // **********************************************************************************************
        // Configure the Stage
        // **********************************************************************************************
        primaryStage.setTitle("Test Application");
        primaryStage.show();
    }

    private void configureTableView() {

        // **********************************************************************************************
        // Just a standard sample TableView
        // **********************************************************************************************

        TableColumn<Person, String> colName = new TableColumn<>("Name");
        TableColumn<Person, String> colEmail = new TableColumn<>("Email");

        colName.setCellValueFactory(new PropertyValueFactory<>("name"));
        colEmail.setCellValueFactory(new PropertyValueFactory<>("email"));

        tableView.getColumns().addAll(colName, colEmail);

    }

    private void initDragAndDrop() {

        DataFormat personDataFormat = new DataFormat("Person");

        // **********************************************************************************************
        // Add drag and drop to the TableView
        // **********************************************************************************************
        tableView.setOnDragDetected(event -> {
            // **********************************************************************************************
            // Drag was detected, allow any type of transfer
            // **********************************************************************************************
            Dragboard db = tableView.startDragAndDrop(TransferMode.ANY);

            // **********************************************************************************************
            // Add the selected Person to the clipboard, using our custom DataFormat
            // **********************************************************************************************
            ClipboardContent content = new ClipboardContent();
            content.put(personDataFormat, tableView.getSelectionModel().getSelectedItem());
            db.setContent(content);
        });

        // **********************************************************************************************
        // Add drag and drop to the TextArea
        // **********************************************************************************************
        textArea.setOnDragOver(event -> {

            // **********************************************************************************************
            // Person was dragged over the TextArea; accept it only if dragged from a node other than itself.
            // In this case, this condition isn't necessary, but still good practice
            // **********************************************************************************************
            if (event.getGestureSource() != textArea
                && event.getDragboard().hasContent(personDataFormat)) {

                // **********************************************************************************************
                // For this example, we'll allow ANY transfer type again
                // **********************************************************************************************
                event.acceptTransferModes(TransferMode.ANY);

            }

            // **********************************************************************************************
            // Consume the event. We'll handle placing content into the TextArea next
            // **********************************************************************************************
            event.consume();
        });

        // **********************************************************************************************
        // Add handler to the TextArea to accept a Person object that's been dropped and add the person's
        // name to the TextArea
        // **********************************************************************************************
        textArea.setOnDragDropped(event -> {

            // **********************************************************************************************
            // First, ensure the object being dropped was a Person object
            // **********************************************************************************************
            Dragboard db = event.getDragboard();
            boolean success = false;
            if (db.hasContent(personDataFormat)) {

                // **********************************************************************************************
                // Get a reference to the Person being dropped. Note that you need to 
                // cast the object to a Person so Java knows what object type you're 
                // working with.
                // **********************************************************************************************
                Person droppedPerson = (Person) db.getContent(personDataFormat);
                textArea.appendText(droppedPerson.getName() + "\n");

                success = true;
            }

            // **********************************************************************************************
            // Complete the event
            // **********************************************************************************************
            event.setDropCompleted(success);

            event.consume();
        });

    }

    private ObservableList<Person> sampleData() {
        // **********************************************************************************************
        // Just some sample Persons for our TableView
        // **********************************************************************************************
        return FXCollections.observableList(Arrays.asList(
                new Person("John Williams", "jwilliams@et.com"),
                new Person("Howard Shore", "hshore@shire.com"),
                new Person("Danny Elfman", "delfman@scissorpalace.org")));

    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

截屏