我遇到了另一个JavaFX问题。为了使问题的故事很短:
我有两个带有项目的TableView,我想在相应的TableView中拖放。我在momemt遇到的问题是我可以将项目放在我从中得到它的同一个TableView中。情况应该不是这样,我想阻止这种情况。
有没有办法限制目标表,如果有,我该怎么办?
非常感谢你的帮助!
实现了setOnDragOver方法:
selectedParticipantsTable.setOnDragOver(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
// data is dragged over the target
Dragboard db = event.getDragboard();
if (db.hasContent(participantsDataFormat)){
if(selectedParticipantsTableData.contains(db.getContent(participantsDataFormat)) != true){
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
else
{
event.acceptTransferModes(TransferMode.NONE);
}
}
event.consume();
}
});
好的,我想我还有点进一步。我创建了一个自己的DataFormat来将项目放在DragBoard的ClipBoard中。现在的问题是MetaData类中的SimpleStringProperties不可序列化,我不知道如何正确,因为当我将项目拖到另一个TableView上时,我总是得到一个EOFExceptio。
有什么建议吗?
答案 0 :(得分:1)
您只能将可序列化对象放到拖拽板上的限制是一个真正的痛苦。即使你使你的模型类可序列化(这很困难,因为JavaFX属性不可序列化,但并非不可能),它可能不会做你想要的,因为你将获得拖动对象的副本而不是对原始对象的引用。
我唯一的解决方法是将拖动的对象存储在一个实例变量中(如果drop的代码与拖动代码的类不同,那么你需要更复杂的东西)。
以下是使用Oracle教程中常用联系表的SSCCE:
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.scene.Scene;
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.HBox;
import javafx.stage.Stage;
public class TwoTablesDragging extends Application {
private static final String DRAGGING_PERSON_KEY = "dragging-person";
private Person currentDraggedPerson ;
@Override
public void start(Stage primaryStage) {
TableView<Person> contacts = createPersonTable();
TableView<Person> selectedContacts = createPersonTable();
contacts.getItems().addAll(
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")
);
HBox root = new HBox(10, contacts, selectedContacts);
root.setPadding(new Insets(10));
primaryStage.setScene(new Scene(root, 800, 600));
primaryStage.show();
}
private void setUpDragAndDrop(TableView<Person> table) {
// note: It's generally better to set drag detected on the table rows, using
// a rowFactory, so you don't rely on selection. This is just a "quick and dirty"
// approach for a demo
table.setOnDragDetected(e -> {
Dragboard db = table.startDragAndDrop(TransferMode.COPY_OR_MOVE);
ClipboardContent content = new ClipboardContent();
content.putString(DRAGGING_PERSON_KEY);
db.setContent(content);
currentDraggedPerson = table.getSelectionModel().getSelectedItem();
});
table.setOnDragOver(e -> {
Dragboard db = e.getDragboard();
if (DRAGGING_PERSON_KEY.equals(db.getString()) &&
! table.getItems().contains(currentDraggedPerson)) {
e.acceptTransferModes(TransferMode.MOVE);
}
});
table.setOnDragDropped(e -> {
Dragboard db = e.getDragboard();
if (DRAGGING_PERSON_KEY.equals(db.getString())) {
table.getItems().add(currentDraggedPerson);
e.setDropCompleted(true);
} else {
e.setDropCompleted(false);
}
});
table.setOnDragDone(e -> {
if (e.getTransferMode() == TransferMode.MOVE) {
table.getItems().remove(currentDraggedPerson);
currentDraggedPerson = null ;
}
});
}
private TableView<Person> createPersonTable() {
TableView<Person> table = new TableView<>();
table.getColumns().add(column("First Name", Person::firstNameProperty, 100));
table.getColumns().add(column("Last Name", Person::lastNameProperty, 100));
table.getColumns().add(column("Email", Person::emailProperty, 175));
setUpDragAndDrop(table);
return table ;
}
private <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> prop, double width) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> prop.apply(cellData.getValue()));
col.setPrefWidth(width);
return col ;
}
public static class Person {
private StringProperty firstName = new SimpleStringProperty();
private StringProperty lastName = new SimpleStringProperty();
private 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 java.lang.String getFirstName() {
return this.firstNameProperty().get();
}
public final void setFirstName(final java.lang.String firstName) {
this.firstNameProperty().set(firstName);
}
public final StringProperty lastNameProperty() {
return this.lastName;
}
public final java.lang.String getLastName() {
return this.lastNameProperty().get();
}
public final void setLastName(final java.lang.String lastName) {
this.lastNameProperty().set(lastName);
}
public final StringProperty emailProperty() {
return this.email;
}
public final java.lang.String getEmail() {
return this.emailProperty().get();
}
public final void setEmail(final java.lang.String email) {
this.emailProperty().set(email);
}
}
public static void main(String[] args) {
launch(args);
}
}