Windows 如何防止在JavaFXTableView中拖放列时触发事件

Windows 如何防止在JavaFXTableView中拖放列时触发事件,windows,spring-boot,java-8,javafx-8,Windows,Spring Boot,Java 8,Javafx 8,在SpringBootJavaFX应用程序中,我有多个表视图。允许用户使用默认的拖放功能对列重新排序。我还有一个监听器来检测其中一个TableView中的另一行是否被选中,并相应地采取一些措施: /* * Processing when a selection in a table changes. */ getTableView().getSelectionModel().selectedItemProperty().addListener((observable, oldValue,

在SpringBootJavaFX应用程序中,我有多个表视图。允许用户使用默认的拖放功能对列重新排序。我还有一个监听器来检测其中一个TableView中的另一行是否被选中,并相应地采取一些措施:

/*
 * Processing when a selection in a table changes.
 */ 
getTableView().getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
    this.detailsController.get().showDetails(newValue);
});
问题是,当一个列被拖放(在操作的拖放部分)时,这个侦听器会被激活。这有不希望的副作用,因为在这种情况下,变量newValue是“null”(它本身就是处理的有效值,我只是不想在拖动列后删除该列时传递该值)。在删除列时,是否有方法绕过此侦听器

我尝试了各种方法来捕捉拖放事件,但都没有用……我想我可以在拖放开始时停用侦听器,并在拖放完成后重新激活

以下是一些示例代码:

import java.util.Arrays;
import java.util.List;
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.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TestDragDrop 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));

        table.getItems().addAll(createData());
        
        table.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue == null) {
                System.out.println("===>>> Oops");
            } else {
                System.out.println("===>>> Hi there " + newValue.getFirstName());
            }
        });

        VBox checkBoxes = new VBox(5);
        checkBoxes.getStyleClass().add("controls");

        BorderPane root = new BorderPane(table);
        root.setTop(checkBoxes);

        Scene scene = new Scene(root, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    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);
    }
}
导入java.util.array;
导入java.util.List;
导入java.util.function.function;
导入javafx.application.application;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.beans.value.observeValue;
导入javafx.scene.scene;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TableView;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.layout.VBox;
导入javafx.stage.stage;
公共类TestDragDrop扩展了应用程序{
@凌驾
公共无效开始(阶段primaryStage){
TableView table=新TableView();
table.getColumns().add(column(“First Name”,Person::firstNameProperty));
table.getColumns().add(列(“姓氏”,Person::lastNameProperty));
table.getColumns().add(column(“Email”,Person::emailProperty));
table.getItems().addAll(createData());
table.getSelectionModel().SelectEditeProperty().addListener((可观察、旧值、新值)->{
if(newValue==null){
System.out.println(“==>>>Oops”);
}否则{
System.out.println(“==>>>你好”+newValue.getFirstName());
}
});
VBox复选框=新的VBox(5);
checkbox.getStyleClass().add(“控件”);
BorderPane根=新的BorderPane(表);
root.setTop(复选框);
场景=新场景(根,800600);
初级阶段。场景(场景);
primaryStage.show();
}
私有静态TableColumn列(字符串文本、函数属性){
TableColumn col=新的TableColumn(文本);
col.setCellValueFactory(cellData->property.apply(cellData.getValue());
返回列;
}
私有列表createData(){
返回数组.asList(新人(“Jacob”、“Smith”、“Jacob”)。smith@example.com"),
新人(“伊莎贝拉”、“约翰逊”、“伊莎贝拉”。johnson@example.com"),
新人(“伊桑”、“威廉姆斯”、“伊桑”。williams@example.com"),
新人(“艾玛”、“琼斯”、“艾玛”。jones@example.com"),
新人(“迈克尔”、“布朗”、“迈克尔”。brown@example.com"));
}
公共静态类人员{
private final StringProperty firstName=新SimpleStringProperty();
private final StringProperty lastName=新的SimpleStringProperty();
private final StringProperty email=新SimpleStringProperty();
公众人物(stringfirstname、stringlastname、stringemail){
setFirstName(firstName);
setLastName(lastName);
设置电子邮件(电子邮件);
}
公共最终StringProperty firstNameProperty(){
返回这个.firstName;
}
公共最终字符串getFirstName(){
返回此.firstNameProperty().get();
}
公共最终void setFirstName(最终字符串firstName){
this.firstNameProperty().set(firstName);
}
公共最终StringProperty lastNameProperty(){
返回this.lastName;
}
公共最终字符串getLastName(){
返回此.lastNameProperty().get();
}
公共最终void setLastName(最终字符串lastName){
this.lastNameProperty().set(lastName);
}
公共最终StringProperty emailProperty(){
返回此电子邮件;
}
公共最终字符串getEmail(){
返回此.emailProperty().get();
}
公开最终作废设置电子邮件(最终字符串电子邮件){
this.emailProperty().set(电子邮件);
}
}
公共静态void main(字符串[]args){
发射(args);
}
}

在表中选择一行:==>>>您好。。。。输出到控制台。现在将第一列拖动到表中的另一个位置:==>>>Oops被输出到控制台。

因此,防止这种情况发生的一种方法是添加一个缓冲区,在该列释放后的一段时间内防止更改

在我的例子中,我使用了50ms作为缓冲区,因为在我的测试中,拖到0.05秒时,人很难完成拖动并点击一个名字,这很好(没有通过空值),但可以根据需要增加/减少

在这里,我初始化PauseTransfion,它将在给定时间后触发

private final PauseTransition bufferReset = new PauseTransition(Duration.millis(50));
private boolean isBuffering = false;
初始化后,将变量设置为翻转回不再缓冲

bufferReset.setOnFinished(event -> isBuffering = false);
下一段代码是在列被释放后翻转缓冲区变量,并启动计时器将变量翻转回来

Platform.runLater(() -> {
    for (Node header : table.lookupAll("TableHeaderRow")) {
        if(header instanceof TableHeaderRow) {
            header.addEventFilter(MouseEvent.MOUSE_RELEASED, event -> {
                isBuffering = true;
                bufferReset.play();
            });
        }
    }
});
然后将代码包装到isBuffering if语句中

if(!isBuffering) {
    if (newValue == null) {
        System.out.println("===>>> Oops");
    } else {
        System.out.println("===>>> Hi there " + newValue.getFirstName());
    }
}
完整代码(不包括人员类别):

公共类TestDragDrop扩展了应用程序{
专用最终PauseTransition bufferReset=新的PauseTransition(持续时间.millis(50));
私有布尔isBuffering=false;
@凌驾
公共无效开始(阶段primaryStage){
TableView table=新TableView();
table.getColumns().add(第一列
public class TestDragDrop extends Application {

    private final PauseTransition bufferReset = new PauseTransition(Duration.millis(50));
    private boolean isBuffering = false;

    @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));

        table.getItems().addAll(createData());

        table.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if(!isBuffering) {
                if (newValue == null) {
                    System.out.println("===>>> Oops");
                } else {
                    System.out.println("===>>> Hi there " + newValue.getFirstName());
                }
            }
        });

        bufferReset.setOnFinished(event -> isBuffering = false);

        Platform.runLater(() -> {
            for (Node header : table.lookupAll("TableHeaderRow")) {
                if(header instanceof TableHeaderRow) {
                    header.addEventFilter(MouseEvent.MOUSE_RELEASED, event -> {
                        isBuffering = true;
                        bufferReset.play();
                    });
                }
            }
        });

        VBox checkBoxes = new VBox(5);
        checkBoxes.getStyleClass().add("controls");

        BorderPane root = new BorderPane(table);
        root.setTop(checkBoxes);

        Scene scene = new Scene(root, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    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 void main(String[] args) { launch(args); }

}