JavaFX - 将一行从表格视图拖到文本区域中
JavaFX - drag a row from a tableview into a textarea
考虑 JavaFX 应用程序中的表视图。表格视图包含有关人员的数据:
id firstname lastname
1 John Doe
tableview 的每一行都可以用来实例化一个 Person 对象:
new Person(Integer id, String firstname, String lastname)
.
这是我想要做的:
我想 select 表格视图中的其中一个人物,然后用鼠标将其拖到文本区域中。在文本区域内,我想打印字符串:
1 John Doe
.
我知道我必须实现三个功能才能实现此目的:onDragDetected(), onDragOver() and onDragDropped()
。
我想从以下开始:
public void onDragDetected(DragEvent dragevent) {
Person person = tvPersonData.getSelectionModel().getSelectedItem();
}
这行得通。但我必须以某种方式让我的 Person 进入 DragBoard 对象 (dragevent.getDragboard()
)。我想我知道。然后也许我的其他功能可以使用我的拖板中的任何内容。
有人可以帮我吗?
为了在DragAndDrop
手势中使用自定义对象,您需要为对象定义自定义DataFormat
:
DataFormat personDataFormat = new DataFormat("com.package.Person");
您显然需要将 com.package.Person
替换为您为其创建的 class 的完整路径。
另请注意,为了将 class 用作 DataFormat
,class 必须是 Serializable
。这是通过在 Person
对象中实现 Serializable
接口来实现的:
class Person implements Serializable {}
另一件事要记住,JavaFX 属性不是 Serializable
,所以如果您在 Person
对象中使用 StringProperty
,这将不起作用;您需要创建一个包装器 class 来保存您需要的数据。
一旦您的 DataFormat
和 Person
实现了 Serializable
,您就可以将 Person
对象复制到剪贴板,就像任何其他内容一样;你只需要为它指定 DataFormat
:
ClipboardContent content = new ClipboardContent();
content.put(personDataFormat, tableView.getSelectionModel().getSelectedItem());
落入 TextArea
将是相似的。您将定义 DataFormat
,然后根据需要添加要处理的代码:
Person droppedPerson = (Person) db.getContent(personDataFormat);
textArea.appendText(droppedPerson.getName() + "\n");
完整示例应用如下:
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")));
}
}
RESULT:
考虑 JavaFX 应用程序中的表视图。表格视图包含有关人员的数据:
id firstname lastname
1 John Doe
tableview 的每一行都可以用来实例化一个 Person 对象:
new Person(Integer id, String firstname, String lastname)
.
这是我想要做的:
我想 select 表格视图中的其中一个人物,然后用鼠标将其拖到文本区域中。在文本区域内,我想打印字符串:
1 John Doe
.
我知道我必须实现三个功能才能实现此目的:onDragDetected(), onDragOver() and onDragDropped()
。
我想从以下开始:
public void onDragDetected(DragEvent dragevent) {
Person person = tvPersonData.getSelectionModel().getSelectedItem();
}
这行得通。但我必须以某种方式让我的 Person 进入 DragBoard 对象 (dragevent.getDragboard()
)。我想我知道。然后也许我的其他功能可以使用我的拖板中的任何内容。
有人可以帮我吗?
为了在DragAndDrop
手势中使用自定义对象,您需要为对象定义自定义DataFormat
:
DataFormat personDataFormat = new DataFormat("com.package.Person");
您显然需要将 com.package.Person
替换为您为其创建的 class 的完整路径。
另请注意,为了将 class 用作 DataFormat
,class 必须是 Serializable
。这是通过在 Person
对象中实现 Serializable
接口来实现的:
class Person implements Serializable {}
另一件事要记住,JavaFX 属性不是 Serializable
,所以如果您在 Person
对象中使用 StringProperty
,这将不起作用;您需要创建一个包装器 class 来保存您需要的数据。
一旦您的 DataFormat
和 Person
实现了 Serializable
,您就可以将 Person
对象复制到剪贴板,就像任何其他内容一样;你只需要为它指定 DataFormat
:
ClipboardContent content = new ClipboardContent();
content.put(personDataFormat, tableView.getSelectionModel().getSelectedItem());
落入 TextArea
将是相似的。您将定义 DataFormat
,然后根据需要添加要处理的代码:
Person droppedPerson = (Person) db.getContent(personDataFormat);
textArea.appendText(droppedPerson.getName() + "\n");
完整示例应用如下:
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")));
}
}
RESULT: