微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何防止在 JavaFX TableView 中拖放列时触发事件

如何解决如何防止在 JavaFX TableView 中拖放列时触发事件

在我的 Spring Boot JavaFX 应用程序中,我有多个 TableView。允许用户使用认的拖放功能对列重新排序。我还有一个侦听器来检测这些 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,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);
    }
}

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

解决方法

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

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

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

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

完整代码(不包括person类):

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

}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。