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

威廉·昆克尔斯

在我的Spring Boot JavaFX应用程序中,我具有多个TableViews。允许用户使用默认的拖放功能对列进行重新排序。我也有一个侦听器,用于检测在其中一个TableViews中是否选择了另一行,并采取相应的措施:

/*
 * 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", "[email protected]"),
                new Person("Isabella", "Johnson", "[email protected]"),
                new Person("Ethan", "Williams", "[email protected]"),
                new Person("Emma", "Jones", "[email protected]"),
                new Person("Michael", "Brown", "[email protected]"));
    }

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

在表中选择一行:=== >>> Hi .....输出到控制台。现在,将第一列拖到表中的其他位置:=== >>> Oops输出到控制台。

马特

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

在我的情况下,我使用50ms作为缓冲区,因为在此时间内,一个人很难完成拖动并单击名称,因为在我的测试中结果达到0.05秒,这很好(没有通过null),但是增加了/根据需要减少

在这里,我初始化了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());
    }
}

完整代码(不包括人员类别):

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", "[email protected]"),
                new Person("Isabella", "Johnson", "[email protected]"),
                new Person("Ethan", "Williams", "[email protected]"),
                new Person("Emma", "Jones", "[email protected]"),
                new Person("Michael", "Brown", "[email protected]"));
    }

    public static void main(String[] args) { launch(args); }

}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何防止JavaFX中的窗口太小?

使用角度日历拖放事件时防止eventClick触发

JavaFX TextField如何防止在按键事件中键入键

如何防止拖动时触发滑动事件

如何防止在comboBox中的项目在javafx中重复?

JavaFX Text防止底层触发鼠标事件

如何防止laravel在测试中触发事件?

JavaFX拖放:当节点的边界与目标重叠时,触发Target上的DragEntered事件

如何防止TableView在javaFX 8中进行TableColumn重新排序?

如何防止在JavaFX中的TableView中选择另一行

从输入中删除字符时,如何防止keyup事件触发两次?

防止在 JavaScript 中冒泡和捕获时触发事件

触发onPaste事件时防止keyUp事件

在 C# 中触发另一个事件时,如何防止一个事件方法完成?

JavaFX:如何触发TreeItem事件

如何在 JavaFx 中当运动改变其方向时触发事件

在更改事件中隐藏元素时如何停止触发事件

如何防止在 VB.Net 中触发 Checkbox Checkchanged 事件

如何防止跳过屏幕旋转触发的 onResume 事件中的功能?

如何对TableView JavaFx中的列进行排序?

如何在JavaFX中防止在SPACE键上关闭AutoCompleteCombobox popupmenu

如何防止排队的事件回调触发?

如何防止退格键触发 onkeyup 事件?

如何防止<label>事件触发关联的元素?

在Javafx 2.4.0中过渡停止后如何触发事件?

当从另一个事件中调用.val()时,防止在输入上触发“ change”事件

在实际尝试触发双击事件时,如何防止双击事件的再次执行?

当已经有子元素时,防止drop事件?拖放

单击div时防止触发焦点事件